@easysui/sdk 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/README.md +108 -0
- package/dist/index.d.mts +118 -0
- package/dist/index.d.ts +118 -0
- package/dist/index.js +598 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +556 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +66 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path = require('path');
|
|
4
|
+
var fs3 = require('fs');
|
|
5
|
+
var dotenv = require('dotenv');
|
|
6
|
+
var client = require('@mysten/sui/client');
|
|
7
|
+
var cryptography = require('@mysten/sui/cryptography');
|
|
8
|
+
var ed25519 = require('@mysten/sui/keypairs/ed25519');
|
|
9
|
+
var secp256k1 = require('@mysten/sui/keypairs/secp256k1');
|
|
10
|
+
var secp256r1 = require('@mysten/sui/keypairs/secp256r1');
|
|
11
|
+
var transactions = require('@mysten/sui/transactions');
|
|
12
|
+
var bcs = require('@mysten/sui/bcs');
|
|
13
|
+
var child_process = require('child_process');
|
|
14
|
+
var faucet$1 = require('@mysten/sui/faucet');
|
|
15
|
+
|
|
16
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
|
+
|
|
18
|
+
function _interopNamespace(e) {
|
|
19
|
+
if (e && e.__esModule) return e;
|
|
20
|
+
var n = Object.create(null);
|
|
21
|
+
if (e) {
|
|
22
|
+
Object.keys(e).forEach(function (k) {
|
|
23
|
+
if (k !== 'default') {
|
|
24
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
25
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
get: function () { return e[k]; }
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
n.default = e;
|
|
33
|
+
return Object.freeze(n);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
37
|
+
var fs3__namespace = /*#__PURE__*/_interopNamespace(fs3);
|
|
38
|
+
var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
|
|
39
|
+
|
|
40
|
+
// src/config/config.ts
|
|
41
|
+
function getKeypair(privkey) {
|
|
42
|
+
const parsed = cryptography.decodeSuiPrivateKey(privkey);
|
|
43
|
+
switch (parsed.scheme) {
|
|
44
|
+
case "ED25519": {
|
|
45
|
+
return ed25519.Ed25519Keypair.fromSecretKey(parsed.secretKey);
|
|
46
|
+
}
|
|
47
|
+
case "Secp256k1": {
|
|
48
|
+
return secp256k1.Secp256k1Keypair.fromSecretKey(parsed.secretKey);
|
|
49
|
+
}
|
|
50
|
+
case "Secp256r1": {
|
|
51
|
+
return secp256r1.Secp256r1Keypair.fromSecretKey(parsed.secretKey);
|
|
52
|
+
}
|
|
53
|
+
default:
|
|
54
|
+
throw new Error(`Key scheme ${parsed.schema} not supported`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/config/static.ts
|
|
59
|
+
var STATIC_CONFIGS = {
|
|
60
|
+
testnet: {
|
|
61
|
+
USDC_PACKAGE_ID: "0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29"
|
|
62
|
+
},
|
|
63
|
+
mainnet: {
|
|
64
|
+
USDC_PACKAGE_ID: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7"
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// src/config/config.ts
|
|
69
|
+
dotenv__default.default.config({ path: path__default.default.resolve(process.cwd(), ".env") });
|
|
70
|
+
var DENY_LIST_ID = "0x403";
|
|
71
|
+
var CLOCK_ID = "0x6";
|
|
72
|
+
var ADMIN_KEYPAIR = getKeypair(process.env.ADMIN_PRIVATE_KEY);
|
|
73
|
+
var Config = class _Config {
|
|
74
|
+
static instance = null;
|
|
75
|
+
static getInstance() {
|
|
76
|
+
if (!_Config.instance) {
|
|
77
|
+
this.instance = new _Config();
|
|
78
|
+
}
|
|
79
|
+
return this.instance;
|
|
80
|
+
}
|
|
81
|
+
get env() {
|
|
82
|
+
let env = process.env.NODE_ENV;
|
|
83
|
+
if (!["mainnet", "testnet", "devnet", "localnet"].includes(env || "")) {
|
|
84
|
+
env = "localnet";
|
|
85
|
+
}
|
|
86
|
+
return env;
|
|
87
|
+
}
|
|
88
|
+
static get vars() {
|
|
89
|
+
const instance = this.getInstance();
|
|
90
|
+
const NETWORK = instance.env;
|
|
91
|
+
dotenv__default.default.config({ path: path__default.default.resolve(process.cwd(), `.env.${NETWORK}`), override: true });
|
|
92
|
+
const envVars = {
|
|
93
|
+
NETWORK,
|
|
94
|
+
RPC: client.getFullnodeUrl(NETWORK),
|
|
95
|
+
PACKAGE_PATH: process.env.PACKAGE_PATH || "",
|
|
96
|
+
PACKAGE_ID: process.env.PACKAGE_ID || "",
|
|
97
|
+
UPGRADE_CAP_ID: process.env.UPGRADE_CAP_ID || "",
|
|
98
|
+
USDC_TREASURY_CAP: process.env.USDC_TREASURY_CAP,
|
|
99
|
+
USDC_PACKAGE_ID: process.env.USDC_PACKAGE_ID
|
|
100
|
+
};
|
|
101
|
+
const staticVars = STATIC_CONFIGS[NETWORK] || {};
|
|
102
|
+
return {
|
|
103
|
+
...staticVars,
|
|
104
|
+
...envVars
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
static write(config) {
|
|
108
|
+
const instance = this.getInstance();
|
|
109
|
+
const env = instance.env;
|
|
110
|
+
const envFile = path__default.default.join(process.cwd(), `.env${env ? `.${env}` : ""}`);
|
|
111
|
+
const envVariables = Object.entries(config).filter(([_, value]) => value).map(([key, value]) => `${key}=${value}`).join("\n");
|
|
112
|
+
fs3__namespace.default.writeFileSync(envFile, envVariables, "utf8");
|
|
113
|
+
return envFile;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
var COST_ANALYSIS_FILE = "./gas_cost_estimation.csv";
|
|
117
|
+
var HEADERS = [
|
|
118
|
+
"environment",
|
|
119
|
+
"executedAt",
|
|
120
|
+
"digest",
|
|
121
|
+
"packageId",
|
|
122
|
+
"call",
|
|
123
|
+
"computationCost",
|
|
124
|
+
"storageCost",
|
|
125
|
+
"storageRebate",
|
|
126
|
+
"nonRefundableStorageFee",
|
|
127
|
+
"gasSpent"
|
|
128
|
+
];
|
|
129
|
+
function analyze_cost(ptb, resp) {
|
|
130
|
+
if (!process.env.COST_ANALYZER_ENABLED) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (!fs3__namespace.existsSync(COST_ANALYSIS_FILE)) {
|
|
134
|
+
fs3__namespace.writeFileSync(COST_ANALYSIS_FILE, HEADERS.join(",") + "\n");
|
|
135
|
+
}
|
|
136
|
+
const columns = [Config.vars.NETWORK, Date.now(), resp.digest];
|
|
137
|
+
const moveCalls = ptb.blockData.transactions.filter((txItem) => txItem.kind === "MoveCall");
|
|
138
|
+
const moveCall = moveCalls.pop();
|
|
139
|
+
if (!moveCall?.target) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const splits = moveCall.target.split("::");
|
|
143
|
+
columns.push(splits[0]);
|
|
144
|
+
columns.push(`${splits[1]}::${splits[2]}`);
|
|
145
|
+
const gasUsed = resp.effects?.gasUsed;
|
|
146
|
+
columns.push(gasUsed?.computationCost || "N/A");
|
|
147
|
+
columns.push(gasUsed?.storageCost || "N/A");
|
|
148
|
+
columns.push(gasUsed?.storageRebate || "N/A");
|
|
149
|
+
columns.push(gasUsed?.nonRefundableStorageFee || "N/A");
|
|
150
|
+
const totalGasCost = BigInt(gasUsed?.computationCost || 0) + BigInt(gasUsed?.storageCost || 0);
|
|
151
|
+
const gasSpent = totalGasCost - BigInt(gasUsed?.storageRebate || 0);
|
|
152
|
+
columns.push(gasSpent);
|
|
153
|
+
fs3__namespace.appendFileSync(COST_ANALYSIS_FILE, columns.join(",") + "\n");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// src/utils/sui_client.ts
|
|
157
|
+
var MoveType = /* @__PURE__ */ ((MoveType2) => {
|
|
158
|
+
MoveType2[MoveType2["u8"] = 0] = "u8";
|
|
159
|
+
MoveType2[MoveType2["u16"] = 1] = "u16";
|
|
160
|
+
MoveType2[MoveType2["u32"] = 2] = "u32";
|
|
161
|
+
MoveType2[MoveType2["u64"] = 3] = "u64";
|
|
162
|
+
MoveType2[MoveType2["u128"] = 4] = "u128";
|
|
163
|
+
MoveType2[MoveType2["u256"] = 5] = "u256";
|
|
164
|
+
MoveType2[MoveType2["bool"] = 6] = "bool";
|
|
165
|
+
MoveType2[MoveType2["string"] = 7] = "string";
|
|
166
|
+
MoveType2[MoveType2["object"] = 8] = "object";
|
|
167
|
+
MoveType2[MoveType2["address"] = 9] = "address";
|
|
168
|
+
MoveType2[MoveType2["address_opt"] = 10] = "address_opt";
|
|
169
|
+
MoveType2[MoveType2["vec_address"] = 11] = "vec_address";
|
|
170
|
+
return MoveType2;
|
|
171
|
+
})(MoveType || {});
|
|
172
|
+
var SuiClient = class _SuiClient {
|
|
173
|
+
static instance = null;
|
|
174
|
+
client;
|
|
175
|
+
constructor() {
|
|
176
|
+
this.client = new client.SuiClient({ url: Config.vars.RPC });
|
|
177
|
+
}
|
|
178
|
+
static getInstance() {
|
|
179
|
+
if (!_SuiClient.instance) {
|
|
180
|
+
this.instance = new _SuiClient();
|
|
181
|
+
}
|
|
182
|
+
return this.instance;
|
|
183
|
+
}
|
|
184
|
+
static get client() {
|
|
185
|
+
return this.getInstance().client;
|
|
186
|
+
}
|
|
187
|
+
static async signAndExecute(ptb, signer, errorHandler = (e) => e) {
|
|
188
|
+
try {
|
|
189
|
+
const resp = await _SuiClient.client.signAndExecuteTransaction({
|
|
190
|
+
transaction: ptb,
|
|
191
|
+
signer,
|
|
192
|
+
options: {
|
|
193
|
+
showEffects: true,
|
|
194
|
+
showObjectChanges: true,
|
|
195
|
+
showBalanceChanges: true
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
await _SuiClient.client.waitForTransaction({ digest: resp.digest });
|
|
199
|
+
if (resp.effects?.status.status !== "success") {
|
|
200
|
+
throw new Error(JSON.stringify(resp));
|
|
201
|
+
}
|
|
202
|
+
analyze_cost(ptb, resp);
|
|
203
|
+
return resp;
|
|
204
|
+
} catch (e) {
|
|
205
|
+
throw new Error(errorHandler(e));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
static toMoveArg(ptb, value, type) {
|
|
209
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
210
|
+
return value;
|
|
211
|
+
}
|
|
212
|
+
if (!type) {
|
|
213
|
+
if (typeof value === "string") {
|
|
214
|
+
if (value.startsWith("0x")) {
|
|
215
|
+
type = 8 /* object */;
|
|
216
|
+
} else {
|
|
217
|
+
type = 7 /* string */;
|
|
218
|
+
}
|
|
219
|
+
} else if (typeof value === "boolean") {
|
|
220
|
+
type = 6 /* bool */;
|
|
221
|
+
} else if (typeof value === "number" || typeof value === "bigint") {
|
|
222
|
+
type = 3 /* u64 */;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const factory = {
|
|
226
|
+
[0 /* u8 */]: (v) => ptb.pure.u8(v),
|
|
227
|
+
[1 /* u16 */]: (v) => ptb.pure.u16(v),
|
|
228
|
+
[2 /* u32 */]: (v) => ptb.pure.u32(v),
|
|
229
|
+
[3 /* u64 */]: (v) => ptb.pure.u64(v),
|
|
230
|
+
[4 /* u128 */]: (v) => ptb.pure.u128(v),
|
|
231
|
+
[5 /* u256 */]: (v) => ptb.pure.u256(v),
|
|
232
|
+
[6 /* bool */]: (v) => ptb.pure.bool(v),
|
|
233
|
+
[7 /* string */]: (v) => ptb.pure.string(v),
|
|
234
|
+
[8 /* object */]: (v) => ptb.object(v),
|
|
235
|
+
[9 /* address */]: (v) => ptb.pure.address(v),
|
|
236
|
+
[10 /* address_opt */]: (v) => ptb.pure.option("address", v),
|
|
237
|
+
[11 /* vec_address */]: (v) => ptb.pure.vector("address", v)
|
|
238
|
+
};
|
|
239
|
+
return factory[type](value);
|
|
240
|
+
}
|
|
241
|
+
static async moveCall({
|
|
242
|
+
signer,
|
|
243
|
+
target,
|
|
244
|
+
typeArgs = [],
|
|
245
|
+
args = [],
|
|
246
|
+
argTypes = [],
|
|
247
|
+
errorHandler = (e) => e,
|
|
248
|
+
ptb,
|
|
249
|
+
withTransfer = false
|
|
250
|
+
}) {
|
|
251
|
+
ptb = ptb || new transactions.Transaction();
|
|
252
|
+
const obj = ptb.moveCall({
|
|
253
|
+
target,
|
|
254
|
+
typeArguments: typeArgs,
|
|
255
|
+
arguments: args.map((arg, i) => _SuiClient.toMoveArg(ptb, arg, argTypes[i]))
|
|
256
|
+
});
|
|
257
|
+
if (withTransfer) {
|
|
258
|
+
ptb.transferObjects([obj], signer.toSuiAddress());
|
|
259
|
+
}
|
|
260
|
+
return _SuiClient.signAndExecute(ptb, signer, errorHandler);
|
|
261
|
+
}
|
|
262
|
+
static async public_transfer(objects, from, to) {
|
|
263
|
+
const tx = new transactions.Transaction();
|
|
264
|
+
tx.transferObjects(objects, to);
|
|
265
|
+
return await _SuiClient.signAndExecute(tx, from);
|
|
266
|
+
}
|
|
267
|
+
static async devInspect(ptb, sender) {
|
|
268
|
+
return await _SuiClient.client.devInspectTransactionBlock({
|
|
269
|
+
transactionBlock: ptb,
|
|
270
|
+
sender
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
static async devInspectRaw(ptb, sender) {
|
|
274
|
+
const result = await this.devInspect(ptb, sender);
|
|
275
|
+
return result.results?.[0].returnValues?.[0]?.[0];
|
|
276
|
+
}
|
|
277
|
+
static async devInspectBool(ptb, sender) {
|
|
278
|
+
const result = await this.devInspectRaw(ptb, sender);
|
|
279
|
+
return result && result[0] === 1;
|
|
280
|
+
}
|
|
281
|
+
static async devInspectU64(ptb, sender) {
|
|
282
|
+
const value = await this.devInspectRaw(ptb, sender);
|
|
283
|
+
return BigInt(bcs.bcs.u64().parse(new Uint8Array(value)));
|
|
284
|
+
}
|
|
285
|
+
static async devInspectAddress(ptb, sender) {
|
|
286
|
+
const value = await this.devInspectRaw(ptb, sender);
|
|
287
|
+
if (!value) {
|
|
288
|
+
return void 0;
|
|
289
|
+
}
|
|
290
|
+
const bytes = Uint8Array.from(value);
|
|
291
|
+
return "0x" + Buffer.from(bytes).toString("hex");
|
|
292
|
+
}
|
|
293
|
+
static async getObject(id) {
|
|
294
|
+
return _SuiClient.client.getObject({
|
|
295
|
+
id,
|
|
296
|
+
options: { showContent: true }
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
static async getObjectsByType(owner, type) {
|
|
300
|
+
const res = await _SuiClient.client.getOwnedObjects({
|
|
301
|
+
owner,
|
|
302
|
+
filter: {
|
|
303
|
+
StructType: type
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
return res.data.map((o) => o.data?.objectId).filter((o) => o);
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
var Coin = class {
|
|
310
|
+
static get coinType() {
|
|
311
|
+
throw new Error("`coinType` getter must be implemented !");
|
|
312
|
+
}
|
|
313
|
+
static async getBalance(owner) {
|
|
314
|
+
const result = await SuiClient.client.getBalance({
|
|
315
|
+
owner,
|
|
316
|
+
coinType: this.coinType
|
|
317
|
+
});
|
|
318
|
+
return BigInt(result.totalBalance);
|
|
319
|
+
}
|
|
320
|
+
static async getCoin(owner, amount) {
|
|
321
|
+
const balance = amount || await this.getBalance(owner.toSuiAddress());
|
|
322
|
+
const tx = new transactions.Transaction();
|
|
323
|
+
const coinSplit = transactions.coinWithBalance({
|
|
324
|
+
balance,
|
|
325
|
+
useGasCoin: false,
|
|
326
|
+
type: this.coinType
|
|
327
|
+
});
|
|
328
|
+
tx.transferObjects([coinSplit], owner.toSuiAddress());
|
|
329
|
+
const result = await SuiClient.signAndExecute(tx, owner);
|
|
330
|
+
const coin = result.objectChanges?.find(
|
|
331
|
+
(o) => o.type === "created" && o.objectType === `0x2::coin::Coin<${this.coinType}>`
|
|
332
|
+
);
|
|
333
|
+
return coin?.objectId;
|
|
334
|
+
}
|
|
335
|
+
static async _mint(treasuryId, amount, minter) {
|
|
336
|
+
await SuiClient.moveCall({
|
|
337
|
+
signer: minter,
|
|
338
|
+
target: `0x2::coin::mint`,
|
|
339
|
+
typeArgs: [this.coinType],
|
|
340
|
+
args: [treasuryId, amount],
|
|
341
|
+
argTypes: [8 /* object */, 3 /* u64 */],
|
|
342
|
+
withTransfer: true
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
static async send(amount, from, to) {
|
|
346
|
+
const coin = await this.getCoin(from, amount);
|
|
347
|
+
const ptb = new transactions.Transaction();
|
|
348
|
+
ptb.transferObjects([ptb.object(coin)], to);
|
|
349
|
+
await SuiClient.signAndExecute(ptb, from);
|
|
350
|
+
}
|
|
351
|
+
static async assertBalance(wallet, amount) {
|
|
352
|
+
await expect(this.getBalance(wallet.toSuiAddress())).resolves.toBe(amount);
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// src/tokens/usdc.ts
|
|
357
|
+
var USDC = class extends Coin {
|
|
358
|
+
static get coinType() {
|
|
359
|
+
return Config.vars.USDC_PACKAGE_ID + "::usdc::USDC";
|
|
360
|
+
}
|
|
361
|
+
static async getMintCapId(admin) {
|
|
362
|
+
async function getMintCapFromChain() {
|
|
363
|
+
const mintCapIds = await SuiClient.getObjectsByType(
|
|
364
|
+
admin.toSuiAddress(),
|
|
365
|
+
`${Config.vars.USDC_PACKAGE_ID}::treasury::MintCap`
|
|
366
|
+
);
|
|
367
|
+
return mintCapIds.pop();
|
|
368
|
+
}
|
|
369
|
+
let mintCapId = await getMintCapFromChain();
|
|
370
|
+
if (!mintCapId) {
|
|
371
|
+
await SuiClient.moveCall({
|
|
372
|
+
signer: admin,
|
|
373
|
+
target: `${Config.vars.USDC_PACKAGE_ID}::treasury::configure_new_controller`,
|
|
374
|
+
typeArgs: [this.coinType],
|
|
375
|
+
args: [Config.vars.USDC_TREASURY_CAP, admin.toSuiAddress(), admin.toSuiAddress()],
|
|
376
|
+
argTypes: [8 /* object */, 9 /* address */, 9 /* address */]
|
|
377
|
+
});
|
|
378
|
+
mintCapId = await getMintCapFromChain();
|
|
379
|
+
}
|
|
380
|
+
return mintCapId;
|
|
381
|
+
}
|
|
382
|
+
static async faucet(amount, receiver, admin) {
|
|
383
|
+
const mintCapId = await this.getMintCapId(admin);
|
|
384
|
+
await SuiClient.moveCall({
|
|
385
|
+
signer: admin,
|
|
386
|
+
target: `${Config.vars.USDC_PACKAGE_ID}::treasury::configure_minter`,
|
|
387
|
+
typeArgs: [this.coinType],
|
|
388
|
+
args: [Config.vars.USDC_TREASURY_CAP, DENY_LIST_ID, amount],
|
|
389
|
+
argTypes: [8 /* object */, 8 /* object */, 3 /* u64 */]
|
|
390
|
+
});
|
|
391
|
+
await SuiClient.moveCall({
|
|
392
|
+
signer: admin,
|
|
393
|
+
target: `${Config.vars.USDC_PACKAGE_ID}::treasury::mint`,
|
|
394
|
+
typeArgs: [this.coinType],
|
|
395
|
+
args: [Config.vars.USDC_TREASURY_CAP, mintCapId, DENY_LIST_ID, amount, receiver],
|
|
396
|
+
argTypes: [
|
|
397
|
+
8 /* object */,
|
|
398
|
+
8 /* object */,
|
|
399
|
+
8 /* object */,
|
|
400
|
+
3 /* u64 */,
|
|
401
|
+
9 /* address */
|
|
402
|
+
]
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
var PublishSingleton = class _PublishSingleton {
|
|
407
|
+
constructor(publishResp) {
|
|
408
|
+
this.publishResp = publishResp;
|
|
409
|
+
}
|
|
410
|
+
static instance = null;
|
|
411
|
+
static getDeployVars(signer, packagePath) {
|
|
412
|
+
signer ??= ADMIN_KEYPAIR;
|
|
413
|
+
packagePath ??= Config.vars.PACKAGE_PATH;
|
|
414
|
+
if (!packagePath) {
|
|
415
|
+
throw new Error(
|
|
416
|
+
"You must set the `PACKAGE_PATH` environment variable to your Move.toml path."
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
return [signer, packagePath];
|
|
420
|
+
}
|
|
421
|
+
static async publish(signer, packagePath) {
|
|
422
|
+
const [_signer, _packagePath] = this.getDeployVars(signer, packagePath);
|
|
423
|
+
if (!_PublishSingleton.instance) {
|
|
424
|
+
const publishResp = await _PublishSingleton.publishPackage(_signer, _packagePath);
|
|
425
|
+
const packageId = this.findPublishedPackage(publishResp)?.packageId;
|
|
426
|
+
if (!packageId) {
|
|
427
|
+
throw new Error("Expected to find package published");
|
|
428
|
+
}
|
|
429
|
+
_PublishSingleton.instance = new _PublishSingleton(publishResp);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
static getInstance() {
|
|
433
|
+
if (!_PublishSingleton.instance) {
|
|
434
|
+
throw new Error("Use `async PublishSingleton.publish()` first");
|
|
435
|
+
}
|
|
436
|
+
return _PublishSingleton.instance;
|
|
437
|
+
}
|
|
438
|
+
static publishResponse() {
|
|
439
|
+
return this.getInstance().publishResp;
|
|
440
|
+
}
|
|
441
|
+
static get packageId() {
|
|
442
|
+
const packageChng = this.findPublishedPackage(this.publishResponse());
|
|
443
|
+
if (!packageChng) {
|
|
444
|
+
throw new Error("Expected to find package published");
|
|
445
|
+
}
|
|
446
|
+
return packageChng.packageId;
|
|
447
|
+
}
|
|
448
|
+
static findObjectIdByType(type, fail = true) {
|
|
449
|
+
const obj = this.findObjectChangeCreatedByType(this.publishResponse(), type);
|
|
450
|
+
if (fail && !obj) {
|
|
451
|
+
throw new Error(`Expected to find ${type} shared object created.`);
|
|
452
|
+
}
|
|
453
|
+
return obj?.objectId || "";
|
|
454
|
+
}
|
|
455
|
+
static get upgradeCapId() {
|
|
456
|
+
return this.findObjectIdByType(`0x2::package::UpgradeCap`);
|
|
457
|
+
}
|
|
458
|
+
static get usdcTreasuryCap() {
|
|
459
|
+
return this.findObjectIdByType(
|
|
460
|
+
`${this.packageId}::treasury::Treasury<${this.packageId}::usdc::USDC>`,
|
|
461
|
+
false
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
static getPublishTx(packagePath, signer) {
|
|
465
|
+
const transaction = new transactions.Transaction();
|
|
466
|
+
if (!fs3__namespace.default.existsSync(packagePath)) {
|
|
467
|
+
throw new Error(`Package doesn't exist under: ${packagePath}`);
|
|
468
|
+
}
|
|
469
|
+
if (fs3__namespace.default.existsSync(`${packagePath}/Move.lock`)) {
|
|
470
|
+
fs3__namespace.default.unlinkSync(`${packagePath}/Move.lock`);
|
|
471
|
+
}
|
|
472
|
+
fs3__namespace.default.rmSync(`${packagePath}/build`, { recursive: true, force: true });
|
|
473
|
+
let buildCommand = `sui move build --dump-bytecode-as-base64 --path ${packagePath}`;
|
|
474
|
+
const network = Config.vars.NETWORK;
|
|
475
|
+
if (network === "localnet" || network === "devnet") {
|
|
476
|
+
buildCommand += " --with-unpublished-dependencies";
|
|
477
|
+
}
|
|
478
|
+
const { modules, dependencies } = JSON.parse(child_process.execSync(buildCommand, { encoding: "utf-8" }));
|
|
479
|
+
const upgradeCap = transaction.publish({
|
|
480
|
+
modules,
|
|
481
|
+
dependencies
|
|
482
|
+
});
|
|
483
|
+
transaction.transferObjects([upgradeCap], signer.toSuiAddress());
|
|
484
|
+
return transaction;
|
|
485
|
+
}
|
|
486
|
+
static async getPublishBytes(signer, packagePath) {
|
|
487
|
+
const [_signer, _packagePath] = this.getDeployVars(signer, packagePath);
|
|
488
|
+
const transaction = this.getPublishTx(_packagePath, _signer);
|
|
489
|
+
transaction.setSender(_signer.toSuiAddress());
|
|
490
|
+
const client$1 = new client.SuiClient({ url: Config.vars.RPC });
|
|
491
|
+
const txBytes = await transaction.build({ client: client$1 });
|
|
492
|
+
return Buffer.from(txBytes).toString("base64");
|
|
493
|
+
}
|
|
494
|
+
static async publishPackage(signer, packagePath) {
|
|
495
|
+
const transaction = this.getPublishTx(packagePath, signer);
|
|
496
|
+
const client$1 = new client.SuiClient({ url: Config.vars.RPC });
|
|
497
|
+
const resp = await client$1.signAndExecuteTransaction({
|
|
498
|
+
transaction,
|
|
499
|
+
signer,
|
|
500
|
+
options: {
|
|
501
|
+
showObjectChanges: true,
|
|
502
|
+
showEffects: true
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
if (resp.effects?.status.status !== "success") {
|
|
506
|
+
throw new Error(`Failure during publish transaction:
|
|
507
|
+
${JSON.stringify(resp, null, 2)}`);
|
|
508
|
+
}
|
|
509
|
+
await client$1.waitForTransaction({ digest: resp.digest });
|
|
510
|
+
return resp;
|
|
511
|
+
}
|
|
512
|
+
static findPublishedPackage(resp) {
|
|
513
|
+
return resp.objectChanges?.find(
|
|
514
|
+
(chng) => chng.type === "published"
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
static findObjectChangeCreatedByType(resp, type) {
|
|
518
|
+
return resp.objectChanges?.find(
|
|
519
|
+
(chng) => chng.type === "created" && chng.objectType === type
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
// src/utils/deploy.ts
|
|
525
|
+
async function deploy(vars) {
|
|
526
|
+
vars ??= Config.vars;
|
|
527
|
+
await PublishSingleton.publish();
|
|
528
|
+
const newConfig = {
|
|
529
|
+
...vars,
|
|
530
|
+
PACKAGE_ID: PublishSingleton.packageId,
|
|
531
|
+
UPGRADE_CAP_ID: PublishSingleton.upgradeCapId
|
|
532
|
+
};
|
|
533
|
+
if (PublishSingleton.usdcTreasuryCap) {
|
|
534
|
+
newConfig.USDC_PACKAGE_ID = PublishSingleton.packageId;
|
|
535
|
+
newConfig.USDC_TREASURY_CAP = PublishSingleton.usdcTreasuryCap;
|
|
536
|
+
}
|
|
537
|
+
Config.write(newConfig);
|
|
538
|
+
return `Move contracts deployed successfully on ${vars.NETWORK} contract details have been stored in .env.${vars.NETWORK}`;
|
|
539
|
+
}
|
|
540
|
+
async function getDeployBytes() {
|
|
541
|
+
return await PublishSingleton.getPublishBytes();
|
|
542
|
+
}
|
|
543
|
+
function createWallet() {
|
|
544
|
+
return new ed25519.Ed25519Keypair();
|
|
545
|
+
}
|
|
546
|
+
async function createFundedWallet(usdcAmount) {
|
|
547
|
+
const wallet = createWallet();
|
|
548
|
+
await faucet(wallet.toSuiAddress());
|
|
549
|
+
if (usdcAmount) {
|
|
550
|
+
await USDC.faucet(usdcAmount, wallet.toSuiAddress(), ADMIN_KEYPAIR);
|
|
551
|
+
}
|
|
552
|
+
return wallet;
|
|
553
|
+
}
|
|
554
|
+
async function faucet(address) {
|
|
555
|
+
await faucet$1.requestSuiFromFaucetV2({
|
|
556
|
+
host: faucet$1.getFaucetHost(Config.vars.NETWORK),
|
|
557
|
+
// or 'devnet', 'localnet'
|
|
558
|
+
recipient: address
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
function sleep(ms) {
|
|
562
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
563
|
+
}
|
|
564
|
+
async function waitForNextEpoch(timeoutMs = 5 * 60 * 1e3, pollIntervalMs = 2e3) {
|
|
565
|
+
const startEpoch = (await SuiClient.client.getLatestSuiSystemState()).epoch;
|
|
566
|
+
const startTime = Date.now();
|
|
567
|
+
while (true) {
|
|
568
|
+
const { epoch } = await SuiClient.client.getLatestSuiSystemState();
|
|
569
|
+
if (Number(epoch) > Number(startEpoch)) {
|
|
570
|
+
return epoch;
|
|
571
|
+
}
|
|
572
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
573
|
+
throw new Error("Timeout waiting for next epoch.");
|
|
574
|
+
}
|
|
575
|
+
await sleep(pollIntervalMs);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
exports.ADMIN_KEYPAIR = ADMIN_KEYPAIR;
|
|
580
|
+
exports.CLOCK_ID = CLOCK_ID;
|
|
581
|
+
exports.Coin = Coin;
|
|
582
|
+
exports.Config = Config;
|
|
583
|
+
exports.DENY_LIST_ID = DENY_LIST_ID;
|
|
584
|
+
exports.MoveType = MoveType;
|
|
585
|
+
exports.PublishSingleton = PublishSingleton;
|
|
586
|
+
exports.STATIC_CONFIGS = STATIC_CONFIGS;
|
|
587
|
+
exports.SuiClient = SuiClient;
|
|
588
|
+
exports.USDC = USDC;
|
|
589
|
+
exports.analyze_cost = analyze_cost;
|
|
590
|
+
exports.createFundedWallet = createFundedWallet;
|
|
591
|
+
exports.createWallet = createWallet;
|
|
592
|
+
exports.deploy = deploy;
|
|
593
|
+
exports.getDeployBytes = getDeployBytes;
|
|
594
|
+
exports.getKeypair = getKeypair;
|
|
595
|
+
exports.sleep = sleep;
|
|
596
|
+
exports.waitForNextEpoch = waitForNextEpoch;
|
|
597
|
+
//# sourceMappingURL=index.js.map
|
|
598
|
+
//# sourceMappingURL=index.js.map
|