@0xobelisk/sui-cli 1.1.5 → 1.1.7

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.
@@ -2,111 +2,96 @@ import { Dubhe } from '@0xobelisk/sui-client';
2
2
  import * as fs from 'fs';
3
3
  import chalk from 'chalk';
4
4
 
5
- export async function generateAccountHandler(
6
- force: boolean = false,
7
- outputTsPath?: string
8
- ) {
9
- if (outputTsPath) {
10
- console.log(
11
- chalk.blue(
12
- 'Note: The generated account will be stored in the .env file and the TypeScript file specified by the --output-ts-path option.'
13
- )
14
- );
15
- console.log(
16
- chalk.yellow(
17
- 'Warning: Do not expose the key file. It is intended for local testing only.\n'
18
- )
19
- );
20
- }
21
- const path = process.cwd();
22
- let privateKey: string;
5
+ export async function generateAccountHandler(force: boolean = false, outputTsPath?: string) {
6
+ if (outputTsPath) {
7
+ console.log(
8
+ chalk.blue(
9
+ 'Note: The generated account will be stored in the .env file and the TypeScript file specified by the --output-ts-path option.'
10
+ )
11
+ );
12
+ console.log(
13
+ chalk.yellow('Warning: Do not expose the key file. It is intended for local testing only.\n')
14
+ );
15
+ }
16
+ const path = process.cwd();
17
+ let privateKey: string;
23
18
 
24
- if (force) {
25
- const dubhe = new Dubhe();
26
- const keypair = dubhe.getSigner();
27
- privateKey = keypair.getSecretKey();
19
+ if (force) {
20
+ const dubhe = new Dubhe();
21
+ const keypair = dubhe.getSigner();
22
+ privateKey = keypair.getSecretKey();
28
23
 
29
- fs.writeFileSync(`${path}/.env`, `PRIVATE_KEY=${privateKey}`);
30
- console.log(chalk.green(`File created at: ${path}/.env`));
24
+ fs.writeFileSync(`${path}/.env`, `PRIVATE_KEY=${privateKey}`);
25
+ console.log(chalk.green(`File created at: ${path}/.env`));
31
26
 
32
- if (outputTsPath) {
33
- const dir = outputTsPath.substring(
34
- 0,
35
- outputTsPath.lastIndexOf('/')
36
- );
37
- if (!fs.existsSync(dir)) {
38
- fs.mkdirSync(dir, { recursive: true });
39
- }
40
- fs.writeFileSync(
41
- outputTsPath,
42
- `export const PRIVATEKEY = '${privateKey}';
27
+ if (outputTsPath) {
28
+ const dir = outputTsPath.substring(0, outputTsPath.lastIndexOf('/'));
29
+ if (!fs.existsSync(dir)) {
30
+ fs.mkdirSync(dir, { recursive: true });
31
+ }
32
+ fs.writeFileSync(
33
+ outputTsPath,
34
+ `export const PRIVATEKEY = '${privateKey}';
43
35
  export const ACCOUNT = '${keypair.toSuiAddress()}';
44
36
  `
45
- );
46
- console.log(chalk.green(`File created at: ${outputTsPath}\n`));
47
- }
37
+ );
38
+ console.log(chalk.green(`File created at: ${outputTsPath}\n`));
39
+ }
48
40
 
49
- console.log(
50
- chalk.blue(`Force generate new Account: ${keypair.toSuiAddress()}`)
51
- );
52
- return;
53
- }
41
+ console.log(chalk.blue(`Force generate new Account: ${keypair.toSuiAddress()}`));
42
+ return;
43
+ }
54
44
 
55
- // Check if .env file exists and has content
56
- try {
57
- const envContent = fs.readFileSync(`${path}/.env`, 'utf8');
58
- const match = envContent.match(/PRIVATE_KEY=(.+)/);
59
- if (match && match[1]) {
60
- privateKey = match[1];
61
- const dubhe = new Dubhe({ secretKey: privateKey });
62
- const keypair = dubhe.getSigner();
45
+ // Check if .env file exists and has content
46
+ try {
47
+ const envContent = fs.readFileSync(`${path}/.env`, 'utf8');
48
+ const match = envContent.match(/PRIVATE_KEY=(.+)/);
49
+ if (match && match[1]) {
50
+ privateKey = match[1];
51
+ const dubhe = new Dubhe({ secretKey: privateKey });
52
+ const keypair = dubhe.getSigner();
63
53
 
64
- if (outputTsPath) {
65
- const dir = outputTsPath.substring(
66
- 0,
67
- outputTsPath.lastIndexOf('/')
68
- );
69
- if (!fs.existsSync(dir)) {
70
- fs.mkdirSync(dir, { recursive: true });
71
- }
72
- fs.writeFileSync(
73
- outputTsPath,
74
- `export const PRIVATEKEY = '${privateKey}';
54
+ if (outputTsPath) {
55
+ const dir = outputTsPath.substring(0, outputTsPath.lastIndexOf('/'));
56
+ if (!fs.existsSync(dir)) {
57
+ fs.mkdirSync(dir, { recursive: true });
58
+ }
59
+ fs.writeFileSync(
60
+ outputTsPath,
61
+ `export const PRIVATEKEY = '${privateKey}';
75
62
  export const ACCOUNT = '${keypair.toSuiAddress()}';
76
63
  `
77
- );
78
- console.log(chalk.green(`File created at: ${outputTsPath}\n`));
79
- }
64
+ );
65
+ console.log(chalk.green(`File created at: ${outputTsPath}\n`));
66
+ }
80
67
 
81
- console.log(
82
- chalk.blue(`Using existing Account: ${keypair.toSuiAddress()}`)
83
- );
84
- return;
85
- }
86
- } catch (error) {
87
- // .env file doesn't exist or failed to read, continue to generate new account
88
- }
68
+ console.log(chalk.blue(`Using existing Account: ${keypair.toSuiAddress()}`));
69
+ return;
70
+ }
71
+ } catch (error) {
72
+ // .env file doesn't exist or failed to read, continue to generate new account
73
+ }
89
74
 
90
- // If no existing private key, generate new account
91
- const dubhe = new Dubhe();
92
- const keypair = dubhe.getSigner();
93
- privateKey = keypair.getSecretKey();
94
- fs.writeFileSync(`${path}/.env`, `PRIVATE_KEY=${privateKey}`);
95
- console.log(chalk.green(`File created at: ${path}/.env`));
75
+ // If no existing private key, generate new account
76
+ const dubhe = new Dubhe();
77
+ const keypair = dubhe.getSigner();
78
+ privateKey = keypair.getSecretKey();
79
+ fs.writeFileSync(`${path}/.env`, `PRIVATE_KEY=${privateKey}`);
80
+ console.log(chalk.green(`File created at: ${path}/.env`));
96
81
 
97
- if (outputTsPath) {
98
- const dir = outputTsPath.substring(0, outputTsPath.lastIndexOf('/'));
99
- if (!fs.existsSync(dir)) {
100
- fs.mkdirSync(dir, { recursive: true });
101
- }
102
- fs.writeFileSync(
103
- outputTsPath,
104
- `export const PRIVATEKEY = '${privateKey}';
82
+ if (outputTsPath) {
83
+ const dir = outputTsPath.substring(0, outputTsPath.lastIndexOf('/'));
84
+ if (!fs.existsSync(dir)) {
85
+ fs.mkdirSync(dir, { recursive: true });
86
+ }
87
+ fs.writeFileSync(
88
+ outputTsPath,
89
+ `export const PRIVATEKEY = '${privateKey}';
105
90
  export const ACCOUNT = '${keypair.toSuiAddress()}';
106
91
  `
107
- );
108
- console.log(chalk.green(`File created at: ${outputTsPath}\n`));
109
- }
92
+ );
93
+ console.log(chalk.green(`File created at: ${outputTsPath}\n`));
94
+ }
110
95
 
111
- console.log(chalk.blue(`Generate new Account: ${keypair.toSuiAddress()}`));
96
+ console.log(chalk.blue(`Generate new Account: ${keypair.toSuiAddress()}`));
112
97
  }
@@ -1,24 +1,24 @@
1
1
  import { DubheCliError } from './errors';
2
- import {delay, getSchemaId} from './utils';
2
+ import { delay, getSchemaId } from './utils';
3
3
  import { DubheConfig } from '@0xobelisk/sui-common';
4
- import {getFullnodeUrl, SuiClient, SuiTransactionBlockResponse} from "@mysten/sui/client";
4
+ import { getFullnodeUrl, SuiClient, SuiTransactionBlockResponse } from '@mysten/sui/client';
5
5
  import sqlite3 from 'sqlite3';
6
- import {Database, open} from 'sqlite';
7
- import chalk from "chalk";
6
+ import { Database, open } from 'sqlite';
7
+ import chalk from 'chalk';
8
8
 
9
9
  let sqliteDB: Database;
10
10
 
11
11
  const createDB = async (name: string) => {
12
- sqliteDB = await open({
13
- filename: `./${name}.db`,
14
- driver: sqlite3.Database
15
- });
16
- await createTable(sqliteDB, name);
17
- await createTxsTable(sqliteDB);
18
- return sqliteDB;
19
- }
12
+ sqliteDB = await open({
13
+ filename: `./${name}.db`,
14
+ driver: sqlite3.Database
15
+ });
16
+ await createTable(sqliteDB, name);
17
+ await createTxsTable(sqliteDB);
18
+ return sqliteDB;
19
+ };
20
20
  const createTable = async (sqliteDB: Database, name: string) => {
21
- let sql = `
21
+ let sql = `
22
22
  CREATE TABLE IF NOT EXISTS ${name} (
23
23
  id INTEGER PRIMARY KEY AUTOINCREMENT,
24
24
  last_update_checkpoint TEXT,
@@ -29,87 +29,99 @@ const createTable = async (sqliteDB: Database, name: string) => {
29
29
  value TEXT,
30
30
  is_removed BOOLEAN DEFAULT FALSE
31
31
  )`;
32
- await sqliteDB.exec(sql);
33
- }
32
+ await sqliteDB.exec(sql);
33
+ };
34
34
 
35
35
  const createTxsTable = async (sqliteDB: Database) => {
36
- let sql = `
36
+ let sql = `
37
37
  CREATE TABLE IF NOT EXISTS dapp_transaction (
38
38
  id INTEGER PRIMARY KEY AUTOINCREMENT,
39
39
  checkpoint TEXT,
40
40
  digest TEXT
41
41
  )
42
- `
43
- await sqliteDB.exec(sql);
44
- }
42
+ `;
43
+ await sqliteDB.exec(sql);
44
+ };
45
45
 
46
46
  type SetRecord = {
47
- name: string,
48
- key1: string | object,
49
- key2: string | object,
50
- value: string | object
51
- }
47
+ name: string;
48
+ key1: string | object;
49
+ key2: string | object;
50
+ value: string | object;
51
+ };
52
52
 
53
53
  type RemoveRecord = {
54
- name: string,
55
- key1: string | object,
56
- key2: string | object,
57
- }
54
+ name: string;
55
+ key1: string | object;
56
+ key2: string | object;
57
+ };
58
58
 
59
- const processSetRecord = async (sqliteDB: Database, dbName: string, checkpoint: string, digest: string, event: unknown) => {
60
- let res = event as SetRecord;
61
- if ((typeof res.key1 === 'object' && res.key1 !== null) || Array.isArray(res.key1)) {
62
- res.key1 = serializeData(res.key1);
63
- } else if ((typeof res.key2 === 'object' && res.key2 !== null) || Array.isArray(res.key2)) {
64
- res.key2 = serializeData(res.key2);
65
- } else if (typeof res.value === 'object' || Array.isArray(res.value)) {
66
- res.value = serializeData(res.value);
67
- }
68
- await insertData(sqliteDB, dbName, {
69
- checkpoint: checkpoint,
70
- digest: digest,
71
- event: res
72
- });
73
- }
59
+ const processSetRecord = async (
60
+ sqliteDB: Database,
61
+ dbName: string,
62
+ checkpoint: string,
63
+ digest: string,
64
+ event: unknown
65
+ ) => {
66
+ let res = event as SetRecord;
67
+ if ((typeof res.key1 === 'object' && res.key1 !== null) || Array.isArray(res.key1)) {
68
+ res.key1 = serializeData(res.key1);
69
+ } else if ((typeof res.key2 === 'object' && res.key2 !== null) || Array.isArray(res.key2)) {
70
+ res.key2 = serializeData(res.key2);
71
+ } else if (typeof res.value === 'object' || Array.isArray(res.value)) {
72
+ res.value = serializeData(res.value);
73
+ }
74
+ await insertData(sqliteDB, dbName, {
75
+ checkpoint: checkpoint,
76
+ digest: digest,
77
+ event: res
78
+ });
79
+ };
74
80
 
75
- const processRemoveRecord = async (sqliteDB: Database, dbName: string, checkpoint: string, digest: string, event: unknown) => {
76
- let res = event as RemoveRecord;
77
- if ((typeof res.key1 === 'object' && res.key1 !== null) || Array.isArray(res.key1)) {
78
- res.key1 = serializeData(res.key1);
79
- } else if ((typeof res.key2 === 'object' && res.key2 !== null) || Array.isArray(res.key2)) {
80
- res.key2 = serializeData(res.key2);
81
- }
82
- await removeData(sqliteDB, dbName, {
83
- checkpoint: checkpoint,
84
- digest: digest,
85
- event: res
86
- });
87
- }
81
+ const processRemoveRecord = async (
82
+ sqliteDB: Database,
83
+ dbName: string,
84
+ checkpoint: string,
85
+ digest: string,
86
+ event: unknown
87
+ ) => {
88
+ let res = event as RemoveRecord;
89
+ if ((typeof res.key1 === 'object' && res.key1 !== null) || Array.isArray(res.key1)) {
90
+ res.key1 = serializeData(res.key1);
91
+ } else if ((typeof res.key2 === 'object' && res.key2 !== null) || Array.isArray(res.key2)) {
92
+ res.key2 = serializeData(res.key2);
93
+ }
94
+ await removeData(sqliteDB, dbName, {
95
+ checkpoint: checkpoint,
96
+ digest: digest,
97
+ event: res
98
+ });
99
+ };
88
100
 
89
101
  type SetData = {
90
- checkpoint: string,
91
- digest: string,
92
- event: SetRecord
93
- }
102
+ checkpoint: string;
103
+ digest: string;
104
+ event: SetRecord;
105
+ };
94
106
 
95
107
  type RemoveData = {
96
- checkpoint: string,
97
- digest: string,
98
- event: RemoveRecord
99
- }
108
+ checkpoint: string;
109
+ digest: string;
110
+ event: RemoveRecord;
111
+ };
100
112
 
101
113
  const serializeData = (data: object): string => {
102
- if (data.hasOwnProperty("fields")) {
103
- // @ts-ignore
104
- return JSON.stringify(data["fields"]);
105
- }
106
- return JSON.stringify(data);
114
+ if (data.hasOwnProperty('fields')) {
115
+ // @ts-ignore
116
+ return JSON.stringify(data['fields']);
117
+ }
118
+ return JSON.stringify(data);
107
119
  };
108
120
 
109
121
  async function insertData(sqliteDB: Database, dbName: string, data: SetData) {
110
- const { checkpoint, digest, event } = data;
122
+ const { checkpoint, digest, event } = data;
111
123
 
112
- let sql = `
124
+ let sql = `
113
125
  INSERT OR REPLACE INTO ${dbName} (id, last_update_checkpoint, last_update_digest, name, key1, key2, value)
114
126
  VALUES (
115
127
  (SELECT id FROM ${dbName} WHERE name = ? AND (key1 = ? OR key1 IS NULL) AND (key2 = ? OR key2 IS NULL)),
@@ -117,116 +129,136 @@ async function insertData(sqliteDB: Database, dbName: string, data: SetData) {
117
129
  )
118
130
  `;
119
131
 
120
- const values = [event.name, event.key1, event.key2, checkpoint, digest, event.name, event.key1, event.key2, event.value];
132
+ const values = [
133
+ event.name,
134
+ event.key1,
135
+ event.key2,
136
+ checkpoint,
137
+ digest,
138
+ event.name,
139
+ event.key1,
140
+ event.key2,
141
+ event.value
142
+ ];
121
143
 
122
- await sqliteDB.run(sql, values);
123
- console.log("Insert or update data: ", checkpoint, digest, dbName, data);
144
+ await sqliteDB.run(sql, values);
145
+ console.log('Insert or update data: ', checkpoint, digest, dbName, data);
124
146
  }
125
147
 
126
148
  async function removeData(sqliteDB: Database, dbName: string, data: RemoveData) {
127
- const { checkpoint, digest, event } = data;
149
+ const { checkpoint, digest, event } = data;
128
150
 
129
- let sql = `
151
+ let sql = `
130
152
  UPDATE ${dbName}
131
153
  SET is_removed = TRUE
132
154
  WHERE name = ? AND (key1 = ? OR key1 IS NULL) AND (key2 = ? OR key2 IS NULL)
133
155
  `;
134
156
 
135
- await sqliteDB.run(sql, [event.name, event.key1, event.key2]);
136
- console.log("Remove data: ", checkpoint, digest, dbName, data);
157
+ await sqliteDB.run(sql, [event.name, event.key1, event.key2]);
158
+ console.log('Remove data: ', checkpoint, digest, dbName, data);
137
159
  }
138
160
 
139
161
  async function insertTx(sqliteDB: Database, checkpoint: string, digest: string) {
140
- let sql = `
162
+ let sql = `
141
163
  INSERT INTO dapp_transaction (checkpoint, digest)
142
164
  VALUES (?, ?)
143
165
  `;
144
166
 
145
- await sqliteDB.run(sql, [checkpoint, digest]);
146
- console.log("Insert transaction: ", checkpoint, digest);
167
+ await sqliteDB.run(sql, [checkpoint, digest]);
168
+ console.log('Insert transaction: ', checkpoint, digest);
147
169
  }
148
170
 
149
171
  async function getLastDigest(sqliteDB: Database): Promise<string | null> {
150
- const row = await sqliteDB.get(`
172
+ const row = await sqliteDB.get(`
151
173
  SELECT digest FROM dapp_transaction
152
174
  ORDER BY id DESC
153
175
  LIMIT 1
154
176
  `);
155
177
 
156
- return row ? row.digest : null;
178
+ return row ? row.digest : null;
157
179
  }
158
180
 
159
181
  export async function indexerHandler(
160
- dubheConfig: DubheConfig,
161
- network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
162
- db: string,
163
- schemaId: string | undefined,
182
+ dubheConfig: DubheConfig,
183
+ network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
184
+ db: string,
185
+ schemaId: string | undefined
164
186
  ) {
165
- const path = process.cwd();
166
- const projectPath = `${path}/contracts/${dubheConfig.name}`;
167
-
168
- schemaId = schemaId || (await getSchemaId(projectPath, network));
169
-
170
- console.log('\nšŸš€ Sqlite Started');
171
- console.log(` ā”œā”€ Project: ${projectPath}`);
172
- console.log(` ā”œā”€ Network: ${network}`);
173
- console.log(` ā”œā”€ Database: ${db}`);
174
- console.log(` ā”œā”€ Schema ID: ${schemaId}`);
175
-
176
- if (!schemaId) {
177
- throw new DubheCliError(
178
- `Schema ID not found. Please provide a schema ID with the --schemaId flag.`
179
- );
180
- }
181
- const client = new SuiClient({url: getFullnodeUrl(network) });
182
-
183
- if(db === 'sqlite') {
184
- sqliteDB = await createDB(dubheConfig.name);
185
- while (true) {
186
- await delay(2000);
187
- const cursor = await getLastDigest(sqliteDB)
188
- const response = await client.queryTransactionBlocks({
189
- filter: {
190
- // Transaction: 'FD43PRNS2PyNcYExFxwuouLqTVvonTd6NtDYMiVB7ZxZ'
191
- // MoveFunction: {
192
- // package: '0x2dd117c4f48a6be9d2dd20eff67903ebf07080c7e259c7c589078fe21bb78471',
193
- // module: 'message_system',
194
- // function: 'send'
195
- // }
196
- ChangedObject: schemaId
197
- },
198
- order: "ascending",
199
- cursor: cursor,
200
- // limit: 2,
201
- options: {
202
- showEvents: true
203
- }
204
- });
205
- const txs = response.data as SuiTransactionBlockResponse[]
206
- // console.log("New Transactions: ", txs);
207
- for (const tx of txs) {
208
- await insertTx(sqliteDB, tx.checkpoint?.toString() as string, tx.digest);
209
- if (tx.events) {
210
- for (const event of tx.events) {
211
- // @ts-ignore
212
- if (event.parsedJson.hasOwnProperty("value")) {
213
- await processSetRecord(sqliteDB, dubheConfig.name, tx.checkpoint?.toString() as string, tx.digest, event.parsedJson);
214
- } else {
215
- await processRemoveRecord(sqliteDB, dubheConfig.name, tx.checkpoint?.toString() as string, tx.digest, event.parsedJson);
216
- }
217
- }
218
- }
219
- }
220
- };
221
- } else {
222
- throw new DubheCliError(
223
- `Database "${db}" not supported. Supported databases: sqlite`
224
- );
225
- }
187
+ const path = process.cwd();
188
+ const projectPath = `${path}/contracts/${dubheConfig.name}`;
189
+
190
+ schemaId = schemaId || (await getSchemaId(projectPath, network));
191
+
192
+ console.log('\nšŸš€ Sqlite Started');
193
+ console.log(` ā”œā”€ Project: ${projectPath}`);
194
+ console.log(` ā”œā”€ Network: ${network}`);
195
+ console.log(` ā”œā”€ Database: ${db}`);
196
+ console.log(` ā”œā”€ Schema ID: ${schemaId}`);
197
+
198
+ if (!schemaId) {
199
+ throw new DubheCliError(
200
+ `Schema ID not found. Please provide a schema ID with the --schemaId flag.`
201
+ );
202
+ }
203
+ const client = new SuiClient({ url: getFullnodeUrl(network) });
204
+
205
+ if (db === 'sqlite') {
206
+ sqliteDB = await createDB(dubheConfig.name);
207
+ while (true) {
208
+ await delay(2000);
209
+ const cursor = await getLastDigest(sqliteDB);
210
+ const response = await client.queryTransactionBlocks({
211
+ filter: {
212
+ // Transaction: 'FD43PRNS2PyNcYExFxwuouLqTVvonTd6NtDYMiVB7ZxZ'
213
+ // MoveFunction: {
214
+ // package: '0x2dd117c4f48a6be9d2dd20eff67903ebf07080c7e259c7c589078fe21bb78471',
215
+ // module: 'message_system',
216
+ // function: 'send'
217
+ // }
218
+ ChangedObject: schemaId
219
+ },
220
+ order: 'ascending',
221
+ cursor: cursor,
222
+ // limit: 2,
223
+ options: {
224
+ showEvents: true
225
+ }
226
+ });
227
+ const txs = response.data as SuiTransactionBlockResponse[];
228
+ // console.log("New Transactions: ", txs);
229
+ for (const tx of txs) {
230
+ await insertTx(sqliteDB, tx.checkpoint?.toString() as string, tx.digest);
231
+ if (tx.events) {
232
+ for (const event of tx.events) {
233
+ // @ts-ignore
234
+ if (event.parsedJson.hasOwnProperty('value')) {
235
+ await processSetRecord(
236
+ sqliteDB,
237
+ dubheConfig.name,
238
+ tx.checkpoint?.toString() as string,
239
+ tx.digest,
240
+ event.parsedJson
241
+ );
242
+ } else {
243
+ await processRemoveRecord(
244
+ sqliteDB,
245
+ dubheConfig.name,
246
+ tx.checkpoint?.toString() as string,
247
+ tx.digest,
248
+ event.parsedJson
249
+ );
250
+ }
251
+ }
252
+ }
253
+ }
254
+ }
255
+ } else {
256
+ throw new DubheCliError(`Database "${db}" not supported. Supported databases: sqlite`);
257
+ }
226
258
  }
227
259
 
228
260
  process.on('SIGINT', async () => {
229
- await sqliteDB.close();
230
- console.log(chalk.green('āœ… Sqlite Stopped'));
231
- process.exit();
261
+ await sqliteDB.close();
262
+ console.log(chalk.green('āœ… Sqlite Stopped'));
263
+ process.exit();
232
264
  });
@@ -1,4 +1,4 @@
1
- import chalk from "chalk";
1
+ import chalk from 'chalk';
2
2
 
3
3
  export function printDubhe() {
4
4
  console.log(