@0xobelisk/sui-cli 1.0.8 ā 1.0.9
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/dist/dubhe.js +88 -57
- package/dist/dubhe.js.map +1 -1
- package/package.json +7 -4
- package/src/commands/build.ts +51 -45
- package/src/commands/call.ts +1 -1
- package/src/commands/checkBalance.ts +1 -0
- package/src/commands/faucet.ts +1 -2
- package/src/commands/index.ts +2 -0
- package/src/commands/indexer.ts +61 -0
- package/src/commands/publish.ts +1 -0
- package/src/commands/query.ts +1 -9
- package/src/commands/upgrade.ts +1 -0
- package/src/utils/generateAccount.ts +3 -3
- package/src/utils/index.ts +1 -0
- package/src/utils/indexerHandler.ts +232 -0
- package/src/utils/publishHandler.ts +47 -82
- package/src/utils/queryStorage.ts +4 -15
- package/src/utils/startNode.ts +1 -1
- package/src/utils/storeConfig.ts +5 -13
- package/src/utils/upgradeHandler.ts +28 -80
- package/src/utils/utils.ts +10 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xobelisk/sui-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Tookit for interacting with move eps framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sui",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"dubhe": "./dist/dubhe.js"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@mysten/sui": "^1.
|
|
34
|
+
"@mysten/sui": "^1.19.0",
|
|
35
35
|
"chalk": "^5.0.1",
|
|
36
36
|
"child_process": "^1.0.2",
|
|
37
37
|
"dotenv": "^16.0.3",
|
|
@@ -45,8 +45,11 @@
|
|
|
45
45
|
"yargs": "^17.7.1",
|
|
46
46
|
"zod": "^3.22.3",
|
|
47
47
|
"zod-validation-error": "^1.3.0",
|
|
48
|
-
"@
|
|
49
|
-
"
|
|
48
|
+
"@types/sqlite3": "^3.1.11",
|
|
49
|
+
"sqlite": "^5.1.1",
|
|
50
|
+
"sqlite3": "^5.1.7",
|
|
51
|
+
"@0xobelisk/sui-common": "1.0.4",
|
|
52
|
+
"@0xobelisk/sui-client": "1.0.4"
|
|
50
53
|
},
|
|
51
54
|
"devDependencies": {
|
|
52
55
|
"@types/ejs": "^3.1.1",
|
package/src/commands/build.ts
CHANGED
|
@@ -1,56 +1,62 @@
|
|
|
1
|
-
import type { CommandModule } from
|
|
2
|
-
import { execSync } from
|
|
3
|
-
import chalk from
|
|
1
|
+
import type { CommandModule } from 'yargs';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
4
|
import { DubheConfig, loadConfig } from '@0xobelisk/sui-common';
|
|
5
5
|
import { switchEnv, updateDubheDependency } from '../utils';
|
|
6
6
|
|
|
7
7
|
type Options = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
'config-path': string;
|
|
9
|
+
network: any;
|
|
10
|
+
'dump-bytecode-as-base64'?: boolean;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
const commandModule: CommandModule<Options, Options> = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
14
|
+
command: 'build',
|
|
15
|
+
describe: 'Run tests in Dubhe contracts',
|
|
16
|
+
builder(yargs) {
|
|
17
|
+
return yargs.options({
|
|
18
|
+
'config-path': {
|
|
19
|
+
type: 'string',
|
|
20
|
+
default: 'dubhe.config.ts',
|
|
21
|
+
description: 'Options to pass to forge test',
|
|
22
|
+
},
|
|
23
|
+
network: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
choices: ['mainnet', 'testnet', 'devnet', 'localnet'],
|
|
26
|
+
desc: 'Node network (mainnet/testnet/devnet/localnet)',
|
|
27
|
+
},
|
|
28
|
+
'dump-bytecode-as-base64': {
|
|
29
|
+
type: 'boolean',
|
|
30
|
+
default: false,
|
|
31
|
+
desc: 'Dump bytecode as base64',
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
36
|
+
async handler({
|
|
37
|
+
'config-path': configPath,
|
|
38
|
+
network,
|
|
39
|
+
'dump-bytecode-as-base64': dumpBytecodeAsBase64,
|
|
40
|
+
}) {
|
|
41
|
+
// Start an internal anvil process if no world address is provided
|
|
42
|
+
try {
|
|
43
|
+
console.log('š Running move build');
|
|
44
|
+
const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
|
|
45
|
+
const path = process.cwd();
|
|
46
|
+
const projectPath = `${path}/contracts/${dubheConfig.name}`;
|
|
47
|
+
await switchEnv(network);
|
|
48
|
+
await updateDubheDependency(projectPath + '/Move.toml', network);
|
|
49
|
+
const command = `sui move build --path ${projectPath} ${
|
|
50
|
+
dumpBytecodeAsBase64 ? ` --dump-bytecode-as-base64` : ''
|
|
51
|
+
}`;
|
|
52
|
+
const output = execSync(command, { encoding: 'utf-8' });
|
|
53
|
+
console.log(output);
|
|
54
|
+
} catch (error: any) {
|
|
55
|
+
console.error(chalk.red('Error executing sui move build:'));
|
|
56
|
+
console.log(error.stdout);
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
54
60
|
};
|
|
55
61
|
|
|
56
62
|
export default commandModule;
|
package/src/commands/call.ts
CHANGED
|
@@ -26,7 +26,7 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
26
26
|
type: 'string',
|
|
27
27
|
choices: ['mainnet', 'testnet', 'devnet', 'localnet'],
|
|
28
28
|
desc: 'Node network (mainnet/testnet/devnet/localnet)',
|
|
29
|
-
|
|
29
|
+
default: 'localnet',
|
|
30
30
|
},
|
|
31
31
|
module: {
|
|
32
32
|
type: 'string',
|
package/src/commands/faucet.ts
CHANGED
|
@@ -51,8 +51,7 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
51
51
|
const dubhe = new Dubhe({
|
|
52
52
|
secretKey: privateKeyFormat,
|
|
53
53
|
});
|
|
54
|
-
|
|
55
|
-
faucet_address = keypair.toSuiAddress();
|
|
54
|
+
faucet_address = dubhe.getAddress();
|
|
56
55
|
} else {
|
|
57
56
|
faucet_address = recipient;
|
|
58
57
|
}
|
package/src/commands/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import checkBalance from './checkBalance';
|
|
|
13
13
|
import configStore from './configStore';
|
|
14
14
|
import query from './query';
|
|
15
15
|
import call from './call';
|
|
16
|
+
import indexer from './indexer';
|
|
16
17
|
|
|
17
18
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
|
|
18
19
|
export const commands: CommandModule<any, any>[] = [
|
|
@@ -29,4 +30,5 @@ export const commands: CommandModule<any, any>[] = [
|
|
|
29
30
|
generateKey,
|
|
30
31
|
checkBalance,
|
|
31
32
|
configStore,
|
|
33
|
+
indexer,
|
|
32
34
|
];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { CommandModule } from 'yargs';
|
|
2
|
+
import { logError } from '../utils/errors';
|
|
3
|
+
import { indexerHandler } from '../utils';
|
|
4
|
+
import { loadConfig, DubheConfig } from '@0xobelisk/sui-common';
|
|
5
|
+
|
|
6
|
+
type Options = {
|
|
7
|
+
network: any;
|
|
8
|
+
'config-path': string;
|
|
9
|
+
'db': string;
|
|
10
|
+
'schemaId'?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const commandModule: CommandModule<Options, Options> = {
|
|
14
|
+
command: 'indexer',
|
|
15
|
+
|
|
16
|
+
describe: 'Dubhe indexer',
|
|
17
|
+
|
|
18
|
+
builder(yargs) {
|
|
19
|
+
return yargs.options({
|
|
20
|
+
network: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
choices: ['mainnet', 'testnet', 'devnet', 'localnet'],
|
|
23
|
+
desc: 'Node network (mainnet/testnet/devnet/localnet)',
|
|
24
|
+
default: 'localnet',
|
|
25
|
+
},
|
|
26
|
+
'config-path': {
|
|
27
|
+
type: 'string',
|
|
28
|
+
default: 'dubhe.config.ts',
|
|
29
|
+
desc: 'Configuration file path',
|
|
30
|
+
},
|
|
31
|
+
'schemaId': {
|
|
32
|
+
type: 'string',
|
|
33
|
+
desc: 'Schema ID',
|
|
34
|
+
},
|
|
35
|
+
'db': {
|
|
36
|
+
type: 'string',
|
|
37
|
+
choices: ['sqlite', 'postgres'],
|
|
38
|
+
desc: 'Optional gas budget for the transaction',
|
|
39
|
+
default: 'sqlite',
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
async handler({
|
|
45
|
+
network,
|
|
46
|
+
'config-path': configPath,
|
|
47
|
+
db,
|
|
48
|
+
schemaId: schemaId,
|
|
49
|
+
}) {
|
|
50
|
+
try {
|
|
51
|
+
const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
|
|
52
|
+
await indexerHandler(dubheConfig, network, db, schemaId);
|
|
53
|
+
} catch (error: any) {
|
|
54
|
+
logError(error);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
process.exit(0);
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default commandModule;
|
package/src/commands/publish.ts
CHANGED
package/src/commands/query.ts
CHANGED
|
@@ -7,7 +7,6 @@ type Options = {
|
|
|
7
7
|
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet';
|
|
8
8
|
'config-path'?: string;
|
|
9
9
|
schema: string;
|
|
10
|
-
field: string;
|
|
11
10
|
'object-id'?: string;
|
|
12
11
|
'package-id'?: string;
|
|
13
12
|
'metadata-path'?: string;
|
|
@@ -45,8 +44,8 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
45
44
|
network: {
|
|
46
45
|
type: 'string',
|
|
47
46
|
choices: ['mainnet', 'testnet', 'devnet', 'localnet'],
|
|
47
|
+
default: 'localnet',
|
|
48
48
|
desc: 'Node network (mainnet/testnet/devnet/localnet)',
|
|
49
|
-
demandOption: true,
|
|
50
49
|
},
|
|
51
50
|
'config-path': {
|
|
52
51
|
type: 'string',
|
|
@@ -58,11 +57,6 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
58
57
|
desc: 'Schema name',
|
|
59
58
|
demandOption: true,
|
|
60
59
|
},
|
|
61
|
-
field: {
|
|
62
|
-
type: 'string',
|
|
63
|
-
desc: 'Field name',
|
|
64
|
-
demandOption: true,
|
|
65
|
-
},
|
|
66
60
|
'object-id': {
|
|
67
61
|
type: 'string',
|
|
68
62
|
desc: 'Object ID (optional)',
|
|
@@ -86,7 +80,6 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
86
80
|
network,
|
|
87
81
|
'config-path': configPath,
|
|
88
82
|
schema,
|
|
89
|
-
field,
|
|
90
83
|
'object-id': objectId,
|
|
91
84
|
'package-id': packageId,
|
|
92
85
|
'metadata-path': metadataPath,
|
|
@@ -98,7 +91,6 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
98
91
|
await queryStorage({
|
|
99
92
|
dubheConfig,
|
|
100
93
|
schema,
|
|
101
|
-
field,
|
|
102
94
|
objectId,
|
|
103
95
|
network,
|
|
104
96
|
packageId,
|
package/src/commands/upgrade.ts
CHANGED
|
@@ -18,6 +18,7 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
18
18
|
network: {
|
|
19
19
|
type: 'string',
|
|
20
20
|
choices: ['mainnet', 'testnet', 'devnet', 'localnet'],
|
|
21
|
+
default: 'localnet',
|
|
21
22
|
desc: 'Network of the node (mainnet/testnet/devnet/localnet)',
|
|
22
23
|
},
|
|
23
24
|
'config-path': {
|
|
@@ -23,7 +23,7 @@ export async function generateAccountHandler(
|
|
|
23
23
|
|
|
24
24
|
if (force) {
|
|
25
25
|
const dubhe = new Dubhe();
|
|
26
|
-
const keypair = dubhe.
|
|
26
|
+
const keypair = dubhe.getSigner();
|
|
27
27
|
privateKey = keypair.getSecretKey();
|
|
28
28
|
|
|
29
29
|
fs.writeFileSync(`${path}/.env`, `PRIVATE_KEY=${privateKey}`);
|
|
@@ -59,7 +59,7 @@ export const ACCOUNT = '${keypair.toSuiAddress()}';
|
|
|
59
59
|
if (match && match[1]) {
|
|
60
60
|
privateKey = match[1];
|
|
61
61
|
const dubhe = new Dubhe({ secretKey: privateKey });
|
|
62
|
-
const keypair = dubhe.
|
|
62
|
+
const keypair = dubhe.getSigner();
|
|
63
63
|
|
|
64
64
|
if (outputTsPath) {
|
|
65
65
|
const dir = outputTsPath.substring(
|
|
@@ -89,7 +89,7 @@ export const ACCOUNT = '${keypair.toSuiAddress()}';
|
|
|
89
89
|
|
|
90
90
|
// If no existing private key, generate new account
|
|
91
91
|
const dubhe = new Dubhe();
|
|
92
|
-
const keypair = dubhe.
|
|
92
|
+
const keypair = dubhe.getSigner();
|
|
93
93
|
privateKey = keypair.getSecretKey();
|
|
94
94
|
fs.writeFileSync(`${path}/.env`, `PRIVATE_KEY=${privateKey}`);
|
|
95
95
|
console.log(chalk.green(`File created at: ${path}/.env`));
|
package/src/utils/index.ts
CHANGED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { DubheCliError } from './errors';
|
|
2
|
+
import {delay, getSchemaId} from './utils';
|
|
3
|
+
import { DubheConfig } from '@0xobelisk/sui-common';
|
|
4
|
+
import {getFullnodeUrl, SuiClient, SuiTransactionBlockResponse} from "@mysten/sui/client";
|
|
5
|
+
import sqlite3 from 'sqlite3';
|
|
6
|
+
import {Database, open} from 'sqlite';
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
|
|
9
|
+
let sqliteDB: Database;
|
|
10
|
+
|
|
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
|
+
}
|
|
20
|
+
const createTable = async (sqliteDB: Database, name: string) => {
|
|
21
|
+
let sql = `
|
|
22
|
+
CREATE TABLE IF NOT EXISTS ${name} (
|
|
23
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
24
|
+
last_update_checkpoint TEXT,
|
|
25
|
+
last_update_digest TEXT,
|
|
26
|
+
name TEXT,
|
|
27
|
+
key1 TEXT,
|
|
28
|
+
key2 TEXT,
|
|
29
|
+
value TEXT,
|
|
30
|
+
is_removed BOOLEAN DEFAULT FALSE
|
|
31
|
+
)`;
|
|
32
|
+
await sqliteDB.exec(sql);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const createTxsTable = async (sqliteDB: Database) => {
|
|
36
|
+
let sql = `
|
|
37
|
+
CREATE TABLE IF NOT EXISTS dapp_transaction (
|
|
38
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
39
|
+
checkpoint TEXT,
|
|
40
|
+
digest TEXT
|
|
41
|
+
)
|
|
42
|
+
`
|
|
43
|
+
await sqliteDB.exec(sql);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type SetRecord = {
|
|
47
|
+
name: string,
|
|
48
|
+
key1: string | object,
|
|
49
|
+
key2: string | object,
|
|
50
|
+
value: string | object
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type RemoveRecord = {
|
|
54
|
+
name: string,
|
|
55
|
+
key1: string | object,
|
|
56
|
+
key2: string | object,
|
|
57
|
+
}
|
|
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
|
+
}
|
|
74
|
+
|
|
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
|
+
}
|
|
88
|
+
|
|
89
|
+
type SetData = {
|
|
90
|
+
checkpoint: string,
|
|
91
|
+
digest: string,
|
|
92
|
+
event: SetRecord
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
type RemoveData = {
|
|
96
|
+
checkpoint: string,
|
|
97
|
+
digest: string,
|
|
98
|
+
event: RemoveRecord
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
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);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
async function insertData(sqliteDB: Database, dbName: string, data: SetData) {
|
|
110
|
+
const { checkpoint, digest, event } = data;
|
|
111
|
+
|
|
112
|
+
let sql = `
|
|
113
|
+
INSERT OR REPLACE INTO ${dbName} (id, last_update_checkpoint, last_update_digest, name, key1, key2, value)
|
|
114
|
+
VALUES (
|
|
115
|
+
(SELECT id FROM ${dbName} WHERE name = ? AND (key1 = ? OR key1 IS NULL) AND (key2 = ? OR key2 IS NULL)),
|
|
116
|
+
?, ?, ?, ?, ?, ?
|
|
117
|
+
)
|
|
118
|
+
`;
|
|
119
|
+
|
|
120
|
+
const values = [event.name, event.key1, event.key2, checkpoint, digest, event.name, event.key1, event.key2, event.value];
|
|
121
|
+
|
|
122
|
+
await sqliteDB.run(sql, values);
|
|
123
|
+
console.log("Insert or update data: ", checkpoint, digest, dbName, data);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function removeData(sqliteDB: Database, dbName: string, data: RemoveData) {
|
|
127
|
+
const { checkpoint, digest, event } = data;
|
|
128
|
+
|
|
129
|
+
let sql = `
|
|
130
|
+
UPDATE ${dbName}
|
|
131
|
+
SET is_removed = TRUE
|
|
132
|
+
WHERE name = ? AND (key1 = ? OR key1 IS NULL) AND (key2 = ? OR key2 IS NULL)
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
await sqliteDB.run(sql, [event.name, event.key1, event.key2]);
|
|
136
|
+
console.log("Remove data: ", checkpoint, digest, dbName, data);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function insertTx(sqliteDB: Database, checkpoint: string, digest: string) {
|
|
140
|
+
let sql = `
|
|
141
|
+
INSERT INTO dapp_transaction (checkpoint, digest)
|
|
142
|
+
VALUES (?, ?)
|
|
143
|
+
`;
|
|
144
|
+
|
|
145
|
+
await sqliteDB.run(sql, [checkpoint, digest]);
|
|
146
|
+
console.log("Insert transaction: ", checkpoint, digest);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function getLastDigest(sqliteDB: Database): Promise<string | null> {
|
|
150
|
+
const row = await sqliteDB.get(`
|
|
151
|
+
SELECT digest FROM dapp_transaction
|
|
152
|
+
ORDER BY id DESC
|
|
153
|
+
LIMIT 1
|
|
154
|
+
`);
|
|
155
|
+
|
|
156
|
+
return row ? row.digest : null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export async function indexerHandler(
|
|
160
|
+
dubheConfig: DubheConfig,
|
|
161
|
+
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
162
|
+
db: string,
|
|
163
|
+
schemaId: string | undefined,
|
|
164
|
+
) {
|
|
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
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
process.on('SIGINT', async () => {
|
|
229
|
+
await sqliteDB.close();
|
|
230
|
+
console.log(chalk.green('ā
Sqlite Stopped'));
|
|
231
|
+
process.exit();
|
|
232
|
+
});
|