@0xobelisk/client 0.0.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.
- package/LICENSE +202 -0
- package/README.md +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +757 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +755 -0
- package/dist/index.mjs.map +1 -0
- package/dist/libs/suiAccountManager/crypto.d.ts +1 -0
- package/dist/libs/suiAccountManager/index.d.ts +35 -0
- package/dist/libs/suiAccountManager/keypair.d.ts +21 -0
- package/dist/libs/suiAccountManager/types.d.ts +9 -0
- package/dist/libs/suiAccountManager/util.d.ts +29 -0
- package/dist/libs/suiRpcProvider/defaultChainConfigs.d.ts +8 -0
- package/dist/libs/suiRpcProvider/faucet.d.ts +8 -0
- package/dist/libs/suiRpcProvider/index.d.ts +40 -0
- package/dist/libs/suiRpcProvider/types.d.ts +14 -0
- package/dist/libs/suiTxBuilder/index.d.ts +544 -0
- package/dist/libs/suiTxBuilder/types.d.ts +12 -0
- package/dist/libs/suiTxBuilder/util.d.ts +76 -0
- package/dist/obelisk.d.ts +2857 -0
- package/dist/test/tsconfig.tsbuildinfo +1 -0
- package/dist/types/index.d.ts +11 -0
- package/package.json +152 -0
- package/src/index.ts +10 -0
- package/src/libs/suiAccountManager/crypto.ts +7 -0
- package/src/libs/suiAccountManager/index.ts +72 -0
- package/src/libs/suiAccountManager/keypair.ts +38 -0
- package/src/libs/suiAccountManager/types.ts +10 -0
- package/src/libs/suiAccountManager/util.ts +70 -0
- package/src/libs/suiRpcProvider/defaultChainConfigs.ts +30 -0
- package/src/libs/suiRpcProvider/faucet.ts +57 -0
- package/src/libs/suiRpcProvider/index.ts +114 -0
- package/src/libs/suiRpcProvider/types.ts +17 -0
- package/src/libs/suiTxBuilder/index.ts +245 -0
- package/src/libs/suiTxBuilder/types.ts +32 -0
- package/src/libs/suiTxBuilder/util.ts +84 -0
- package/src/obelisk.ts +297 -0
- package/src/types/index.ts +17 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
Obelisk: () => Obelisk,
|
|
24
|
+
SUI_CLOCK_OBJECT_ID: () => import_sui10.SUI_CLOCK_OBJECT_ID,
|
|
25
|
+
SUI_SYSTEM_STATE_OBJECT_ID: () => import_sui10.SUI_SYSTEM_STATE_OBJECT_ID,
|
|
26
|
+
SuiAccountManager: () => SuiAccountManager,
|
|
27
|
+
SuiRpcProvider: () => SuiRpcProvider,
|
|
28
|
+
SuiTxBlock: () => SuiTxBlock,
|
|
29
|
+
TransactionBlock: () => import_sui10.TransactionBlock
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(src_exports);
|
|
32
|
+
var import_sui10 = require("@mysten/sui.js");
|
|
33
|
+
|
|
34
|
+
// src/obelisk.ts
|
|
35
|
+
var import_sui9 = require("@mysten/sui.js");
|
|
36
|
+
|
|
37
|
+
// src/libs/suiAccountManager/index.ts
|
|
38
|
+
var import_sui3 = require("@mysten/sui.js");
|
|
39
|
+
|
|
40
|
+
// src/libs/suiAccountManager/keypair.ts
|
|
41
|
+
var import_sui = require("@mysten/sui.js");
|
|
42
|
+
var getDerivePathForSUI = (derivePathParams = {}) => {
|
|
43
|
+
const {
|
|
44
|
+
accountIndex = 0,
|
|
45
|
+
isExternal = false,
|
|
46
|
+
addressIndex = 0
|
|
47
|
+
} = derivePathParams;
|
|
48
|
+
return `m/44'/784'/${accountIndex}'/${isExternal ? 1 : 0}'/${addressIndex}'`;
|
|
49
|
+
};
|
|
50
|
+
var getKeyPair = (mnemonics, derivePathParams = {}) => {
|
|
51
|
+
const derivePath = getDerivePathForSUI(derivePathParams);
|
|
52
|
+
return import_sui.Ed25519Keypair.deriveKeypair(mnemonics, derivePath);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// src/libs/suiAccountManager/util.ts
|
|
56
|
+
var import_sui2 = require("@mysten/sui.js");
|
|
57
|
+
var isHex = (str) => /^0x[0-9a-fA-F]+$|^[0-9a-fA-F]+$/.test(str);
|
|
58
|
+
var isBase64 = (str) => /^[a-zA-Z0-9+/]+={0,2}$/g.test(str);
|
|
59
|
+
var fromHEX = (hexStr) => {
|
|
60
|
+
if (!hexStr) {
|
|
61
|
+
throw new Error("cannot parse empty string to Uint8Array");
|
|
62
|
+
}
|
|
63
|
+
const intArr = hexStr.replace("0x", "").match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16));
|
|
64
|
+
if (!intArr || intArr.length === 0) {
|
|
65
|
+
throw new Error(`Unable to parse HEX: ${hexStr}`);
|
|
66
|
+
}
|
|
67
|
+
return Uint8Array.from(intArr);
|
|
68
|
+
};
|
|
69
|
+
var hexOrBase64ToUint8Array = (str) => {
|
|
70
|
+
if (isHex(str)) {
|
|
71
|
+
return fromHEX(str);
|
|
72
|
+
} else if (isBase64(str)) {
|
|
73
|
+
return (0, import_sui2.fromB64)(str);
|
|
74
|
+
} else {
|
|
75
|
+
throw new Error("The string is not a valid hex or base64 string.");
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
var PRIVATE_KEY_SIZE = 32;
|
|
79
|
+
var LEGACY_PRIVATE_KEY_SIZE = 64;
|
|
80
|
+
var normalizePrivateKey = (key) => {
|
|
81
|
+
if (key.length === LEGACY_PRIVATE_KEY_SIZE) {
|
|
82
|
+
key = key.slice(0, PRIVATE_KEY_SIZE);
|
|
83
|
+
} else if (key.length === PRIVATE_KEY_SIZE + 1 && key[0] === 0) {
|
|
84
|
+
return key.slice(1);
|
|
85
|
+
} else if (key.length === PRIVATE_KEY_SIZE) {
|
|
86
|
+
return key;
|
|
87
|
+
}
|
|
88
|
+
throw new Error("invalid secret key");
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// src/libs/suiAccountManager/crypto.ts
|
|
92
|
+
var import_bip39 = require("@scure/bip39");
|
|
93
|
+
var import_english = require("@scure/bip39/wordlists/english");
|
|
94
|
+
var generateMnemonic = (numberOfWords = 24) => {
|
|
95
|
+
const strength = numberOfWords === 12 ? 128 : 256;
|
|
96
|
+
return (0, import_bip39.generateMnemonic)(import_english.wordlist, strength);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// src/libs/suiAccountManager/index.ts
|
|
100
|
+
var SuiAccountManager = class {
|
|
101
|
+
/**
|
|
102
|
+
* Support the following ways to init the SuiToolkit:
|
|
103
|
+
* 1. mnemonics
|
|
104
|
+
* 2. secretKey (base64 or hex)
|
|
105
|
+
* If none of them is provided, will generate a random mnemonics with 24 words.
|
|
106
|
+
*
|
|
107
|
+
* @param mnemonics, 12 or 24 mnemonics words, separated by space
|
|
108
|
+
* @param secretKey, base64 or hex string, when mnemonics is provided, secretKey will be ignored
|
|
109
|
+
*/
|
|
110
|
+
constructor({ mnemonics, secretKey } = {}) {
|
|
111
|
+
this.mnemonics = mnemonics || "";
|
|
112
|
+
this.secretKey = secretKey || "";
|
|
113
|
+
if (!this.mnemonics && !this.secretKey) {
|
|
114
|
+
this.mnemonics = generateMnemonic(24);
|
|
115
|
+
}
|
|
116
|
+
this.currentKeyPair = this.secretKey ? import_sui3.Ed25519Keypair.fromSecretKey(
|
|
117
|
+
normalizePrivateKey(hexOrBase64ToUint8Array(this.secretKey))
|
|
118
|
+
) : getKeyPair(this.mnemonics);
|
|
119
|
+
this.currentAddress = this.currentKeyPair.getPublicKey().toSuiAddress();
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* if derivePathParams is not provided or mnemonics is empty, it will return the currentKeyPair.
|
|
123
|
+
* else:
|
|
124
|
+
* it will generate keyPair from the mnemonic with the given derivePathParams.
|
|
125
|
+
*/
|
|
126
|
+
getKeyPair(derivePathParams) {
|
|
127
|
+
if (!derivePathParams || !this.mnemonics)
|
|
128
|
+
return this.currentKeyPair;
|
|
129
|
+
return getKeyPair(this.mnemonics, derivePathParams);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* if derivePathParams is not provided or mnemonics is empty, it will return the currentAddress.
|
|
133
|
+
* else:
|
|
134
|
+
* it will generate address from the mnemonic with the given derivePathParams.
|
|
135
|
+
*/
|
|
136
|
+
getAddress(derivePathParams) {
|
|
137
|
+
if (!derivePathParams || !this.mnemonics)
|
|
138
|
+
return this.currentAddress;
|
|
139
|
+
return getKeyPair(this.mnemonics, derivePathParams).getPublicKey().toSuiAddress();
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Switch the current account with the given derivePathParams.
|
|
143
|
+
* This is only useful when the mnemonics is provided. For secretKey mode, it will always use the same account.
|
|
144
|
+
*/
|
|
145
|
+
switchAccount(derivePathParams) {
|
|
146
|
+
if (this.mnemonics) {
|
|
147
|
+
this.currentKeyPair = getKeyPair(this.mnemonics, derivePathParams);
|
|
148
|
+
this.currentAddress = this.currentKeyPair.getPublicKey().toSuiAddress();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// src/libs/suiRpcProvider/index.ts
|
|
154
|
+
var import_sui6 = require("@mysten/sui.js");
|
|
155
|
+
|
|
156
|
+
// src/libs/suiRpcProvider/faucet.ts
|
|
157
|
+
var import_sui4 = require("@mysten/sui.js");
|
|
158
|
+
var import_ts_retry_promise = require("ts-retry-promise");
|
|
159
|
+
var requestFaucet = async (address, provider) => {
|
|
160
|
+
console.log("\nRequesting SUI from faucet for address: ", address);
|
|
161
|
+
const headers = {
|
|
162
|
+
authority: "faucet.testnet.sui.io",
|
|
163
|
+
method: "POST",
|
|
164
|
+
path: "/gas",
|
|
165
|
+
scheme: "https",
|
|
166
|
+
accept: "*/*",
|
|
167
|
+
"accept-encoding": "gzip, deflate, br",
|
|
168
|
+
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7",
|
|
169
|
+
"content-length": "105",
|
|
170
|
+
"content-type": "application/json",
|
|
171
|
+
origin: "chrome-extension://opcgpfmipidbgpenhmajoajpbobppdil",
|
|
172
|
+
cookie: '_ga=GA1.1.2092533979.1664032306; sui_io_cookie={"level":["necessary","analytics"],"revision":0,"data":null,"rfc_cookie":false}; _ga_YKP53WJMB0=GS1.1.1680531285.31.0.1680531334.11.0.0; _ga_0GW4F97GFL=GS1.1.1680826187.125.0.1680826187.60.0.0; __cf_bm=6rPjXUwuzUPy4yDlZuXgDj0v7xLPpUd5z0CFGCoN_YI-1680867579-0-AZMhU7/mKUUbUlOa27LmfW6eIFkBkXsPKqYgWjpjWpj2XzDckgUsRu/pxSRGfvXCspn3w7Df+uO1MR/b+XikJU0=; _cfuvid=zjwCXMmu19KBIVo_L9Qbq4TqFXJpophG3.EvFTxqdf4-1680867579342-0-604800000',
|
|
173
|
+
"sec-ch-ua": '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
|
|
174
|
+
"sec-ch-ua-mobile": "?0",
|
|
175
|
+
"sec-ch-ua-platform": "macOS",
|
|
176
|
+
"sec-fetch-dest": "empty",
|
|
177
|
+
"sec-fetch-mode": "cors",
|
|
178
|
+
"sec-fetch-site": "none",
|
|
179
|
+
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
|
|
180
|
+
};
|
|
181
|
+
const resp = await (0, import_ts_retry_promise.retry)(
|
|
182
|
+
() => provider.requestSuiFromFaucet(address, headers),
|
|
183
|
+
{
|
|
184
|
+
backoff: "EXPONENTIAL",
|
|
185
|
+
// overall timeout in 60 seconds
|
|
186
|
+
timeout: 1e3 * 60,
|
|
187
|
+
// skip retry if we hit the rate-limit error
|
|
188
|
+
retryIf: (error) => !(error instanceof import_sui4.FaucetRateLimitError),
|
|
189
|
+
logger: (msg) => console.warn(`Retry requesting faucet: ${msg}`)
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
(0, import_sui4.assert)(resp, import_sui4.FaucetResponse, "Request faucet failed\n");
|
|
193
|
+
console.log("Request faucet success\n");
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// src/libs/suiRpcProvider/defaultChainConfigs.ts
|
|
197
|
+
var import_sui5 = require("@mysten/sui.js");
|
|
198
|
+
var getDefaultNetworkParams = (networkType = "devnet") => {
|
|
199
|
+
switch (networkType) {
|
|
200
|
+
case "localnet":
|
|
201
|
+
return import_sui5.localnetConnection;
|
|
202
|
+
case "devnet":
|
|
203
|
+
return import_sui5.devnetConnection;
|
|
204
|
+
case "testnet":
|
|
205
|
+
return import_sui5.testnetConnection;
|
|
206
|
+
case "mainnet":
|
|
207
|
+
return import_sui5.mainnetConnection;
|
|
208
|
+
default:
|
|
209
|
+
return import_sui5.devnetConnection;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// src/libs/suiRpcProvider/index.ts
|
|
214
|
+
var SuiRpcProvider = class {
|
|
215
|
+
/**
|
|
216
|
+
*
|
|
217
|
+
* @param networkType, 'testnet' | 'mainnet' | 'devnet' | 'localnet', default is 'devnet'
|
|
218
|
+
* @param fullnodeUrl, the fullnode url, default is the preconfig fullnode url for the given network type
|
|
219
|
+
* @param faucetUrl, the faucet url, default is the preconfig faucet url for the given network type
|
|
220
|
+
*/
|
|
221
|
+
constructor({
|
|
222
|
+
fullnodeUrl,
|
|
223
|
+
faucetUrl,
|
|
224
|
+
networkType
|
|
225
|
+
} = {}) {
|
|
226
|
+
const defaultNetworkParams = getDefaultNetworkParams(
|
|
227
|
+
networkType || "devnet"
|
|
228
|
+
);
|
|
229
|
+
this.fullnodeUrl = fullnodeUrl || defaultNetworkParams.fullnode;
|
|
230
|
+
this.faucetUrl = faucetUrl || defaultNetworkParams.faucet;
|
|
231
|
+
const connection = new import_sui6.Connection({
|
|
232
|
+
fullnode: this.fullnodeUrl,
|
|
233
|
+
faucet: this.faucetUrl
|
|
234
|
+
});
|
|
235
|
+
this.provider = new import_sui6.JsonRpcProvider(connection);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Request some SUI from faucet
|
|
239
|
+
* @Returns {Promise<boolean>}, true if the request is successful, false otherwise.
|
|
240
|
+
*/
|
|
241
|
+
async requestFaucet(addr) {
|
|
242
|
+
return requestFaucet(addr, this.provider);
|
|
243
|
+
}
|
|
244
|
+
async getBalance(addr, coinType) {
|
|
245
|
+
return this.provider.getBalance({ owner: addr, coinType });
|
|
246
|
+
}
|
|
247
|
+
async getObjects(ids) {
|
|
248
|
+
const options = { showContent: true, showDisplay: true, showType: true };
|
|
249
|
+
const objects = await this.provider.multiGetObjects({ ids, options });
|
|
250
|
+
const parsedObjects = objects.map((object) => {
|
|
251
|
+
const objectId = (0, import_sui6.getObjectId)(object);
|
|
252
|
+
const objectType = (0, import_sui6.getObjectType)(object);
|
|
253
|
+
const objectVersion = (0, import_sui6.getObjectVersion)(object);
|
|
254
|
+
const objectFields = (0, import_sui6.getObjectFields)(object);
|
|
255
|
+
const objectDisplay = (0, import_sui6.getObjectDisplay)(object);
|
|
256
|
+
return {
|
|
257
|
+
objectId,
|
|
258
|
+
objectType,
|
|
259
|
+
objectVersion,
|
|
260
|
+
objectFields,
|
|
261
|
+
objectDisplay
|
|
262
|
+
};
|
|
263
|
+
});
|
|
264
|
+
return parsedObjects;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* @description Select coins that add up to the given amount.
|
|
268
|
+
* @param addr the address of the owner
|
|
269
|
+
* @param amount the amount that is needed for the coin
|
|
270
|
+
* @param coinType the coin type, default is '0x2::SUI::SUI'
|
|
271
|
+
*/
|
|
272
|
+
async selectCoins(addr, amount, coinType = "0x2::SUI::SUI") {
|
|
273
|
+
const coins = await this.provider.getCoins({ owner: addr, coinType });
|
|
274
|
+
const selectedCoins = [];
|
|
275
|
+
let totalAmount = 0;
|
|
276
|
+
coins.data.sort((a, b) => parseInt(b.balance) - parseInt(a.balance));
|
|
277
|
+
for (const coinData of coins.data) {
|
|
278
|
+
selectedCoins.push({
|
|
279
|
+
objectId: coinData.coinObjectId,
|
|
280
|
+
digest: coinData.digest,
|
|
281
|
+
version: coinData.version
|
|
282
|
+
});
|
|
283
|
+
totalAmount = totalAmount + parseInt(coinData.balance);
|
|
284
|
+
if (totalAmount >= amount) {
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (!selectedCoins.length) {
|
|
289
|
+
throw new Error("No valid coins found for the transaction.");
|
|
290
|
+
}
|
|
291
|
+
return selectedCoins;
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// src/libs/suiTxBuilder/index.ts
|
|
296
|
+
var import_sui8 = require("@mysten/sui.js");
|
|
297
|
+
|
|
298
|
+
// src/libs/suiTxBuilder/util.ts
|
|
299
|
+
var import_sui7 = require("@mysten/sui.js");
|
|
300
|
+
var getDefaultSuiInputType = (value) => {
|
|
301
|
+
if (typeof value === "string" && value.startsWith("0x")) {
|
|
302
|
+
return "object";
|
|
303
|
+
} else if (typeof value === "number" || typeof value === "bigint") {
|
|
304
|
+
return "u64";
|
|
305
|
+
} else if (typeof value === "boolean") {
|
|
306
|
+
return "bool";
|
|
307
|
+
} else {
|
|
308
|
+
return "object";
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
function makeVecParam(txBlock, args, type) {
|
|
312
|
+
if (args.length === 0)
|
|
313
|
+
throw new Error("Transaction builder error: Empty array is not allowed");
|
|
314
|
+
const defaultSuiType = getDefaultSuiInputType(args[0]);
|
|
315
|
+
if (type === "object" || !type && defaultSuiType === "object") {
|
|
316
|
+
const objects = args.map(
|
|
317
|
+
(arg) => typeof arg === "string" ? txBlock.object((0, import_sui7.normalizeSuiObjectId)(arg)) : arg
|
|
318
|
+
);
|
|
319
|
+
return txBlock.makeMoveVec({ objects });
|
|
320
|
+
} else {
|
|
321
|
+
const vecType = type || defaultSuiType;
|
|
322
|
+
return txBlock.pure(args, `vector<${vecType}>`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function isMoveVecArg(arg) {
|
|
326
|
+
const isFullMoveVecArg = arg && arg.value && Array.isArray(arg.value) && arg.vecType;
|
|
327
|
+
const isSimpleMoveVecArg = Array.isArray(arg);
|
|
328
|
+
return isFullMoveVecArg || isSimpleMoveVecArg;
|
|
329
|
+
}
|
|
330
|
+
function convertArgs(txBlock, args) {
|
|
331
|
+
return args.map((arg) => {
|
|
332
|
+
if (typeof arg === "string" && arg.startsWith("0x")) {
|
|
333
|
+
return txBlock.object((0, import_sui7.normalizeSuiObjectId)(arg));
|
|
334
|
+
} else if (isMoveVecArg(arg)) {
|
|
335
|
+
const vecType = arg.vecType || void 0;
|
|
336
|
+
return vecType ? makeVecParam(txBlock, arg.value, vecType) : makeVecParam(txBlock, arg);
|
|
337
|
+
} else if (typeof arg !== "object") {
|
|
338
|
+
return txBlock.pure(arg);
|
|
339
|
+
} else {
|
|
340
|
+
return arg;
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// src/libs/suiTxBuilder/index.ts
|
|
346
|
+
var SuiTxBlock = class {
|
|
347
|
+
constructor(transaction) {
|
|
348
|
+
this.txBlock = new import_sui8.TransactionBlock(transaction);
|
|
349
|
+
}
|
|
350
|
+
//======== override methods of TransactionBlock ============
|
|
351
|
+
address(value) {
|
|
352
|
+
return this.txBlock.pure(value, "address");
|
|
353
|
+
}
|
|
354
|
+
pure(value, type) {
|
|
355
|
+
return this.txBlock.pure(value, type);
|
|
356
|
+
}
|
|
357
|
+
object(value) {
|
|
358
|
+
return this.txBlock.object(value);
|
|
359
|
+
}
|
|
360
|
+
objectRef(ref) {
|
|
361
|
+
return this.txBlock.objectRef(ref);
|
|
362
|
+
}
|
|
363
|
+
sharedObjectRef(ref) {
|
|
364
|
+
return this.txBlock.sharedObjectRef(ref);
|
|
365
|
+
}
|
|
366
|
+
setSender(sender) {
|
|
367
|
+
return this.txBlock.setSender(sender);
|
|
368
|
+
}
|
|
369
|
+
setSenderIfNotSet(sender) {
|
|
370
|
+
return this.txBlock.setSenderIfNotSet(sender);
|
|
371
|
+
}
|
|
372
|
+
setExpiration(expiration) {
|
|
373
|
+
return this.txBlock.setExpiration(expiration);
|
|
374
|
+
}
|
|
375
|
+
setGasPrice(price) {
|
|
376
|
+
return this.txBlock.setGasPrice(price);
|
|
377
|
+
}
|
|
378
|
+
setGasBudget(budget) {
|
|
379
|
+
return this.txBlock.setGasBudget(budget);
|
|
380
|
+
}
|
|
381
|
+
setGasOwner(owner) {
|
|
382
|
+
return this.txBlock.setGasOwner(owner);
|
|
383
|
+
}
|
|
384
|
+
setGasPayment(payments) {
|
|
385
|
+
return this.txBlock.setGasPayment(payments);
|
|
386
|
+
}
|
|
387
|
+
add(transaction) {
|
|
388
|
+
return this.txBlock.add(transaction);
|
|
389
|
+
}
|
|
390
|
+
serialize() {
|
|
391
|
+
return this.txBlock.serialize();
|
|
392
|
+
}
|
|
393
|
+
build(params = {}) {
|
|
394
|
+
return this.txBlock.build(params);
|
|
395
|
+
}
|
|
396
|
+
getDigest({ provider } = {}) {
|
|
397
|
+
return this.txBlock.getDigest({ provider });
|
|
398
|
+
}
|
|
399
|
+
get gas() {
|
|
400
|
+
return this.txBlock.gas;
|
|
401
|
+
}
|
|
402
|
+
get blockData() {
|
|
403
|
+
return this.txBlock.blockData;
|
|
404
|
+
}
|
|
405
|
+
transferObjects(objects, recipient) {
|
|
406
|
+
const tx = this.txBlock;
|
|
407
|
+
tx.transferObjects(convertArgs(this.txBlock, objects), tx.pure(recipient));
|
|
408
|
+
return this;
|
|
409
|
+
}
|
|
410
|
+
splitCoins(coin, amounts) {
|
|
411
|
+
const tx = this.txBlock;
|
|
412
|
+
const coinObject = convertArgs(this.txBlock, [coin])[0];
|
|
413
|
+
const res = tx.splitCoins(
|
|
414
|
+
coinObject,
|
|
415
|
+
amounts.map((m) => tx.pure(m))
|
|
416
|
+
);
|
|
417
|
+
return amounts.map((_, i) => res[i]);
|
|
418
|
+
}
|
|
419
|
+
mergeCoins(destination, sources) {
|
|
420
|
+
const destinationObject = convertArgs(this.txBlock, [destination])[0];
|
|
421
|
+
const sourceObjects = convertArgs(this.txBlock, sources);
|
|
422
|
+
return this.txBlock.mergeCoins(destinationObject, sourceObjects);
|
|
423
|
+
}
|
|
424
|
+
publish(...args) {
|
|
425
|
+
return this.txBlock.publish(...args);
|
|
426
|
+
}
|
|
427
|
+
upgrade(...args) {
|
|
428
|
+
return this.txBlock.upgrade(...args);
|
|
429
|
+
}
|
|
430
|
+
makeMoveVec(...args) {
|
|
431
|
+
return this.txBlock.makeMoveVec(...args);
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* @description Move call
|
|
435
|
+
* @param target `${string}::${string}::${string}`, e.g. `0x3::sui_system::request_add_stake`
|
|
436
|
+
* @param args the arguments of the move call, such as `['0x1', '0x2']`
|
|
437
|
+
* @param typeArgs the type arguments of the move call, such as `['0x2::sui::SUI']`
|
|
438
|
+
*/
|
|
439
|
+
moveCall(target, args = [], typeArgs = []) {
|
|
440
|
+
const regex = /(?<package>[a-zA-Z0-9]+)::(?<module>[a-zA-Z0-9_]+)::(?<function>[a-zA-Z0-9_]+)/;
|
|
441
|
+
const match = target.match(regex);
|
|
442
|
+
if (match === null)
|
|
443
|
+
throw new Error(
|
|
444
|
+
"Invalid target format. Expected `${string}::${string}::${string}`"
|
|
445
|
+
);
|
|
446
|
+
const convertedArgs = convertArgs(this.txBlock, args);
|
|
447
|
+
const tx = this.txBlock;
|
|
448
|
+
return tx.moveCall({
|
|
449
|
+
target,
|
|
450
|
+
arguments: convertedArgs,
|
|
451
|
+
typeArguments: typeArgs
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
//======== enhance methods ============
|
|
455
|
+
transferSuiToMany(recipients, amounts) {
|
|
456
|
+
if (recipients.length !== amounts.length) {
|
|
457
|
+
throw new Error(
|
|
458
|
+
"transferSuiToMany: recipients.length !== amounts.length"
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
const tx = this.txBlock;
|
|
462
|
+
const coins = tx.splitCoins(
|
|
463
|
+
tx.gas,
|
|
464
|
+
amounts.map((amount) => tx.pure(amount))
|
|
465
|
+
);
|
|
466
|
+
recipients.forEach((recipient, index) => {
|
|
467
|
+
tx.transferObjects([coins[index]], tx.pure(recipient));
|
|
468
|
+
});
|
|
469
|
+
return this;
|
|
470
|
+
}
|
|
471
|
+
transferSui(recipient, amount) {
|
|
472
|
+
return this.transferSuiToMany([recipient], [amount]);
|
|
473
|
+
}
|
|
474
|
+
takeAmountFromCoins(coins, amount) {
|
|
475
|
+
const tx = this.txBlock;
|
|
476
|
+
const coinObjects = convertArgs(this.txBlock, coins);
|
|
477
|
+
const mergedCoin = coinObjects[0];
|
|
478
|
+
if (coins.length > 1) {
|
|
479
|
+
tx.mergeCoins(mergedCoin, coinObjects.slice(1));
|
|
480
|
+
}
|
|
481
|
+
const [sendCoin] = tx.splitCoins(mergedCoin, [tx.pure(amount)]);
|
|
482
|
+
return [sendCoin, mergedCoin];
|
|
483
|
+
}
|
|
484
|
+
splitSUIFromGas(amounts) {
|
|
485
|
+
const tx = this.txBlock;
|
|
486
|
+
return tx.splitCoins(
|
|
487
|
+
tx.gas,
|
|
488
|
+
amounts.map((m) => tx.pure(m))
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
splitMultiCoins(coins, amounts) {
|
|
492
|
+
const tx = this.txBlock;
|
|
493
|
+
const coinObjects = convertArgs(this.txBlock, coins);
|
|
494
|
+
const mergedCoin = coinObjects[0];
|
|
495
|
+
if (coins.length > 1) {
|
|
496
|
+
tx.mergeCoins(mergedCoin, coinObjects.slice(1));
|
|
497
|
+
}
|
|
498
|
+
const splitedCoins = tx.splitCoins(
|
|
499
|
+
mergedCoin,
|
|
500
|
+
amounts.map((m) => tx.pure(m))
|
|
501
|
+
);
|
|
502
|
+
return { splitedCoins, mergedCoin };
|
|
503
|
+
}
|
|
504
|
+
transferCoinToMany(inputCoins, sender, recipients, amounts) {
|
|
505
|
+
if (recipients.length !== amounts.length) {
|
|
506
|
+
throw new Error(
|
|
507
|
+
"transferSuiToMany: recipients.length !== amounts.length"
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
const tx = this.txBlock;
|
|
511
|
+
const { splitedCoins, mergedCoin } = this.splitMultiCoins(
|
|
512
|
+
inputCoins,
|
|
513
|
+
amounts
|
|
514
|
+
);
|
|
515
|
+
recipients.forEach((recipient, index) => {
|
|
516
|
+
tx.transferObjects([splitedCoins[index]], tx.pure(recipient));
|
|
517
|
+
});
|
|
518
|
+
tx.transferObjects([mergedCoin], tx.pure(sender));
|
|
519
|
+
return this;
|
|
520
|
+
}
|
|
521
|
+
transferCoin(inputCoins, sender, recipient, amount) {
|
|
522
|
+
return this.transferCoinToMany(inputCoins, sender, [recipient], [amount]);
|
|
523
|
+
}
|
|
524
|
+
stakeSui(amount, validatorAddr) {
|
|
525
|
+
const tx = this.txBlock;
|
|
526
|
+
const [stakeCoin] = tx.splitCoins(tx.gas, [tx.pure(amount)]);
|
|
527
|
+
tx.moveCall({
|
|
528
|
+
target: "0x3::sui_system::request_add_stake",
|
|
529
|
+
arguments: [
|
|
530
|
+
tx.object(import_sui8.SUI_SYSTEM_STATE_OBJECT_ID),
|
|
531
|
+
stakeCoin,
|
|
532
|
+
tx.pure(validatorAddr)
|
|
533
|
+
]
|
|
534
|
+
});
|
|
535
|
+
return tx;
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
// src/obelisk.ts
|
|
540
|
+
var Obelisk = class {
|
|
541
|
+
/**
|
|
542
|
+
* Support the following ways to init the SuiToolkit:
|
|
543
|
+
* 1. mnemonics
|
|
544
|
+
* 2. secretKey (base64 or hex)
|
|
545
|
+
* If none of them is provided, will generate a random mnemonics with 24 words.
|
|
546
|
+
*
|
|
547
|
+
* @param mnemonics, 12 or 24 mnemonics words, separated by space
|
|
548
|
+
* @param secretKey, base64 or hex string, when mnemonics is provided, secretKey will be ignored
|
|
549
|
+
* @param networkType, 'testnet' | 'mainnet' | 'devnet' | 'localnet', default is 'devnet'
|
|
550
|
+
* @param fullnodeUrl, the fullnode url, default is the preconfig fullnode url for the given network type
|
|
551
|
+
* @param faucetUrl, the faucet url, default is the preconfig faucet url for the given network type
|
|
552
|
+
*/
|
|
553
|
+
constructor({
|
|
554
|
+
mnemonics,
|
|
555
|
+
secretKey,
|
|
556
|
+
networkType,
|
|
557
|
+
fullnodeUrl,
|
|
558
|
+
faucetUrl
|
|
559
|
+
} = {}) {
|
|
560
|
+
this.accountManager = new SuiAccountManager({ mnemonics, secretKey });
|
|
561
|
+
this.rpcProvider = new SuiRpcProvider({
|
|
562
|
+
fullnodeUrl,
|
|
563
|
+
faucetUrl,
|
|
564
|
+
networkType
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* if derivePathParams is not provided or mnemonics is empty, it will return the currentSigner.
|
|
569
|
+
* else:
|
|
570
|
+
* it will generate signer from the mnemonic with the given derivePathParams.
|
|
571
|
+
* @param derivePathParams, such as { accountIndex: 2, isExternal: false, addressIndex: 10 }, comply with the BIP44 standard
|
|
572
|
+
*/
|
|
573
|
+
getSigner(derivePathParams) {
|
|
574
|
+
const keyPair = this.accountManager.getKeyPair(derivePathParams);
|
|
575
|
+
return new import_sui9.RawSigner(keyPair, this.rpcProvider.provider);
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* @description Switch the current account with the given derivePathParams
|
|
579
|
+
* @param derivePathParams, such as { accountIndex: 2, isExternal: false, addressIndex: 10 }, comply with the BIP44 standard
|
|
580
|
+
*/
|
|
581
|
+
switchAccount(derivePathParams) {
|
|
582
|
+
this.accountManager.switchAccount(derivePathParams);
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* @description Get the address of the account for the given derivePathParams
|
|
586
|
+
* @param derivePathParams, such as { accountIndex: 2, isExternal: false, addressIndex: 10 }, comply with the BIP44 standard
|
|
587
|
+
*/
|
|
588
|
+
getAddress(derivePathParams) {
|
|
589
|
+
return this.accountManager.getAddress(derivePathParams);
|
|
590
|
+
}
|
|
591
|
+
currentAddress() {
|
|
592
|
+
return this.accountManager.currentAddress;
|
|
593
|
+
}
|
|
594
|
+
provider() {
|
|
595
|
+
return this.rpcProvider.provider;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Request some SUI from faucet
|
|
599
|
+
* @Returns {Promise<boolean>}, true if the request is successful, false otherwise.
|
|
600
|
+
*/
|
|
601
|
+
async requestFaucet(derivePathParams) {
|
|
602
|
+
const addr = this.accountManager.getAddress(derivePathParams);
|
|
603
|
+
return this.rpcProvider.requestFaucet(addr);
|
|
604
|
+
}
|
|
605
|
+
async getBalance(coinType, derivePathParams) {
|
|
606
|
+
const owner = this.accountManager.getAddress(derivePathParams);
|
|
607
|
+
return this.rpcProvider.getBalance(owner, coinType);
|
|
608
|
+
}
|
|
609
|
+
async getObjects(objectIds) {
|
|
610
|
+
return this.rpcProvider.getObjects(objectIds);
|
|
611
|
+
}
|
|
612
|
+
async signTxn(tx, derivePathParams) {
|
|
613
|
+
tx = tx instanceof SuiTxBlock ? tx.txBlock : tx;
|
|
614
|
+
const signer = this.getSigner(derivePathParams);
|
|
615
|
+
return signer.signTransactionBlock({ transactionBlock: tx });
|
|
616
|
+
}
|
|
617
|
+
async signAndSendTxn(tx, derivePathParams) {
|
|
618
|
+
tx = tx instanceof SuiTxBlock ? tx.txBlock : tx;
|
|
619
|
+
const signer = this.getSigner(derivePathParams);
|
|
620
|
+
return signer.signAndExecuteTransactionBlock({
|
|
621
|
+
transactionBlock: tx,
|
|
622
|
+
options: {
|
|
623
|
+
showEffects: true,
|
|
624
|
+
showEvents: true,
|
|
625
|
+
showObjectChanges: true
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Transfer the given amount of SUI to the recipient
|
|
631
|
+
* @param recipient
|
|
632
|
+
* @param amount
|
|
633
|
+
* @param derivePathParams
|
|
634
|
+
*/
|
|
635
|
+
async transferSui(recipient, amount, derivePathParams) {
|
|
636
|
+
const tx = new SuiTxBlock();
|
|
637
|
+
tx.transferSui(recipient, amount);
|
|
638
|
+
return this.signAndSendTxn(tx, derivePathParams);
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Transfer to mutliple recipients
|
|
642
|
+
* @param recipients the recipients addresses
|
|
643
|
+
* @param amounts the amounts of SUI to transfer to each recipient, the length of amounts should be the same as the length of recipients
|
|
644
|
+
* @param derivePathParams
|
|
645
|
+
*/
|
|
646
|
+
async transferSuiToMany(recipients, amounts, derivePathParams) {
|
|
647
|
+
const tx = new SuiTxBlock();
|
|
648
|
+
tx.transferSuiToMany(recipients, amounts);
|
|
649
|
+
return this.signAndSendTxn(tx, derivePathParams);
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Transfer the given amounts of coin to multiple recipients
|
|
653
|
+
* @param recipients the list of recipient address
|
|
654
|
+
* @param amounts the amounts to transfer for each recipient
|
|
655
|
+
* @param coinType any custom coin type but not SUI
|
|
656
|
+
* @param derivePathParams the derive path params for the current signer
|
|
657
|
+
*/
|
|
658
|
+
async transferCoinToMany(recipients, amounts, coinType, derivePathParams) {
|
|
659
|
+
const tx = new SuiTxBlock();
|
|
660
|
+
const owner = this.accountManager.getAddress(derivePathParams);
|
|
661
|
+
const totalAmount = amounts.reduce((a, b) => a + b, 0);
|
|
662
|
+
const coins = await this.rpcProvider.selectCoins(
|
|
663
|
+
owner,
|
|
664
|
+
totalAmount,
|
|
665
|
+
coinType
|
|
666
|
+
);
|
|
667
|
+
tx.transferCoinToMany(
|
|
668
|
+
coins.map((c) => c.objectId),
|
|
669
|
+
owner,
|
|
670
|
+
recipients,
|
|
671
|
+
amounts
|
|
672
|
+
);
|
|
673
|
+
return this.signAndSendTxn(tx, derivePathParams);
|
|
674
|
+
}
|
|
675
|
+
async transferCoin(recipient, amount, coinType, derivePathParams) {
|
|
676
|
+
return this.transferCoinToMany(
|
|
677
|
+
[recipient],
|
|
678
|
+
[amount],
|
|
679
|
+
coinType,
|
|
680
|
+
derivePathParams
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
async transferObjects(objects, recipient, derivePathParams) {
|
|
684
|
+
const tx = new SuiTxBlock();
|
|
685
|
+
tx.transferObjects(objects, recipient);
|
|
686
|
+
return this.signAndSendTxn(tx, derivePathParams);
|
|
687
|
+
}
|
|
688
|
+
async moveCall(callParams) {
|
|
689
|
+
const {
|
|
690
|
+
target,
|
|
691
|
+
arguments: args = [],
|
|
692
|
+
typeArguments = [],
|
|
693
|
+
derivePathParams
|
|
694
|
+
} = callParams;
|
|
695
|
+
const tx = new SuiTxBlock();
|
|
696
|
+
tx.moveCall(target, args, typeArguments);
|
|
697
|
+
return this.signAndSendTxn(tx, derivePathParams);
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Select coins with the given amount and coin type, the total amount is greater than or equal to the given amount
|
|
701
|
+
* @param amount
|
|
702
|
+
* @param coinType
|
|
703
|
+
* @param owner
|
|
704
|
+
*/
|
|
705
|
+
async selectCoinsWithAmount(amount, coinType, owner) {
|
|
706
|
+
owner = owner || this.accountManager.currentAddress;
|
|
707
|
+
const coins = await this.rpcProvider.selectCoins(owner, amount, coinType);
|
|
708
|
+
return coins.map((c) => c.objectId);
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* stake the given amount of SUI to the validator
|
|
712
|
+
* @param amount the amount of SUI to stake
|
|
713
|
+
* @param validatorAddr the validator address
|
|
714
|
+
* @param derivePathParams the derive path params for the current signer
|
|
715
|
+
*/
|
|
716
|
+
async stakeSui(amount, validatorAddr, derivePathParams) {
|
|
717
|
+
const tx = new SuiTxBlock();
|
|
718
|
+
tx.stakeSui(amount, validatorAddr);
|
|
719
|
+
return this.signAndSendTxn(tx, derivePathParams);
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Execute the transaction with on-chain data but without really submitting. Useful for querying the effects of a transaction.
|
|
723
|
+
* Since the transaction is not submitted, its gas cost is not charged.
|
|
724
|
+
* @param tx the transaction to execute
|
|
725
|
+
* @param derivePathParams the derive path params
|
|
726
|
+
* @returns the effects and events of the transaction, such as object changes, gas cost, event emitted.
|
|
727
|
+
*/
|
|
728
|
+
async inspectTxn(tx, derivePathParams) {
|
|
729
|
+
tx = tx instanceof SuiTxBlock ? tx.txBlock : tx;
|
|
730
|
+
return this.rpcProvider.provider.devInspectTransactionBlock({
|
|
731
|
+
transactionBlock: tx,
|
|
732
|
+
sender: this.getAddress(derivePathParams)
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
async call(world_id, system_name, counter, derivePathParams) {
|
|
736
|
+
const tx = new import_sui9.TransactionBlock();
|
|
737
|
+
tx.moveCall({
|
|
738
|
+
target: `${world_id}::system::${system_name}`,
|
|
739
|
+
arguments: [
|
|
740
|
+
// txb.pure(manager),
|
|
741
|
+
tx.pure(counter)
|
|
742
|
+
]
|
|
743
|
+
});
|
|
744
|
+
return this.signAndSendTxn(tx, derivePathParams);
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
748
|
+
0 && (module.exports = {
|
|
749
|
+
Obelisk,
|
|
750
|
+
SUI_CLOCK_OBJECT_ID,
|
|
751
|
+
SUI_SYSTEM_STATE_OBJECT_ID,
|
|
752
|
+
SuiAccountManager,
|
|
753
|
+
SuiRpcProvider,
|
|
754
|
+
SuiTxBlock,
|
|
755
|
+
TransactionBlock
|
|
756
|
+
});
|
|
757
|
+
//# sourceMappingURL=index.js.map
|