@0xobelisk/rooch-client
Version:
Tookit for interacting with rooch move framework
688 lines (676 loc) • 22.5 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __accessCheck = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet = (obj, member, getter) => {
__accessCheck(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
// src/index.ts
var src_exports = {};
__export(src_exports, {
Dubhe: () => Dubhe,
RoochAccountManager: () => RoochAccountManager,
RoochContractFactory: () => RoochContractFactory,
RoochInteractor: () => RoochInteractor,
loadMetadata: () => loadMetadata
});
module.exports = __toCommonJS(src_exports);
__reExport(src_exports, require("@roochnetwork/rooch-sdk"), module.exports);
// src/dubhe.ts
var import_rooch_sdk4 = require("@roochnetwork/rooch-sdk");
// src/libs/roochAccountManager/index.ts
var import_rooch_sdk2 = require("@roochnetwork/rooch-sdk");
// src/libs/roochAccountManager/keypair.ts
var import_rooch_sdk = require("@roochnetwork/rooch-sdk");
var getDerivePathForROOCH = (derivePathParams = {}) => {
const {
accountIndex = 0,
isExternal = false,
addressIndex = 0
} = derivePathParams;
return `m/54'/784'/${accountIndex}'/${isExternal ? 1 : 0}'/${addressIndex}'`;
};
var getKeyPair = (mnemonics, derivePathParams = {}) => {
const derivePath = getDerivePathForROOCH(derivePathParams);
return import_rooch_sdk.Secp256k1Keypair.deriveKeypair(mnemonics, derivePath);
};
// src/libs/roochAccountManager/crypto.ts
var import_bip39 = require("@scure/bip39");
var import_english = require("@scure/bip39/wordlists/english");
var generateMnemonic = (numberOfWords = 24) => {
const strength = numberOfWords === 12 ? 128 : 256;
return (0, import_bip39.generateMnemonic)(import_english.wordlist, strength);
};
// src/libs/roochAccountManager/index.ts
var RoochAccountManager = class {
/**
* Support the following ways to init the SuiToolkit:
* 1. mnemonics
* 2. secretKey (base64 or hex)
* If none of them is provided, will generate a random mnemonics with 24 words.
*
* @param mnemonics, 12 or 24 mnemonics words, separated by space
* @param secretKey, base64 or hex string, when mnemonics is provided, secretKey will be ignored
*/
constructor({ mnemonics, secretKey } = {}) {
this.mnemonics = mnemonics || "";
this.secretKey = secretKey || "";
if (!this.mnemonics && !this.secretKey) {
this.mnemonics = generateMnemonic(24);
}
this.currentKeyPair = this.secretKey ? import_rooch_sdk2.Secp256k1Keypair.fromSecretKey(secretKey) : getKeyPair(this.mnemonics);
this.currentAddress = this.currentKeyPair.getRoochAddress();
this.currentBitcoinAddress = this.currentKeyPair.getBitcoinAddress();
}
/**
* if derivePathParams is not provided or mnemonics is empty, it will return the currentKeyPair.
* else:
* it will generate keyPair from the mnemonic with the given derivePathParams.
*/
getKeyPair(derivePathParams) {
if (!derivePathParams || !this.mnemonics)
return this.currentKeyPair;
return getKeyPair(this.mnemonics, derivePathParams);
}
/**
* if derivePathParams is not provided or mnemonics is empty, it will return the currentAddress.
* else:
* it will generate address from the mnemonic with the given derivePathParams.
*/
getAddress(derivePathParams) {
if (!derivePathParams || !this.mnemonics)
return this.currentAddress;
return getKeyPair(this.mnemonics, derivePathParams).getRoochAddress();
}
getBitcoinAddress(derivePathParams) {
if (!derivePathParams || !this.mnemonics)
return this.currentBitcoinAddress;
return getKeyPair(this.mnemonics, derivePathParams).getBitcoinAddress();
}
/**
* Switch the current account with the given derivePathParams.
* This is only useful when the mnemonics is provided. For secretKey mode, it will always use the same account.
*/
switchAccount(derivePathParams) {
if (this.mnemonics) {
this.currentKeyPair = getKeyPair(this.mnemonics, derivePathParams);
this.currentAddress = this.currentKeyPair.getRoochAddress();
this.currentBitcoinAddress = this.currentKeyPair.getBitcoinAddress();
}
}
};
// src/libs/roochInteractor/roochInteractor.ts
var import_rooch_sdk3 = require("@roochnetwork/rooch-sdk");
// src/libs/roochInteractor/util.ts
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// src/libs/roochInteractor/roochInteractor.ts
var RoochInteractor = class {
constructor(fullNodeUrls, network) {
if (fullNodeUrls.length === 0)
throw new Error("fullNodeUrls must not be empty");
this.clients = fullNodeUrls.map((url) => new import_rooch_sdk3.RoochClient({ url }));
this.currentClient = this.clients[0];
this.fullNodes = fullNodeUrls;
this.currentFullNode = fullNodeUrls[0];
this.network = network;
}
switchToNextProvider() {
const currentClientIdx = this.clients.indexOf(this.currentClient);
this.currentClient = this.clients[(currentClientIdx + 1) % this.clients.length];
this.currentFullNode = this.fullNodes[(currentClientIdx + 1) % this.clients.length];
}
async createSession(sessionArgs, signer) {
for (const client of this.clients) {
try {
const session = await client.createSession({
sessionArgs,
signer
});
return session;
} catch (err) {
console.warn(`Failed to create session: ${err}`);
await delay(2e3);
}
}
throw new Error("Failed to create session with all fullnodes");
}
async signAndExecuteTransaction(transaction, signer, option) {
for (const client of this.clients) {
try {
const txnResponse = await client.signAndExecuteTransaction({
transaction,
signer,
option
});
return txnResponse;
} catch (err) {
console.warn(`Failed to send transaction: ${err}`);
await delay(2e3);
}
}
throw new Error("Failed to send transaction with all fullnodes");
}
async executeViewFunction(contractAddress, moduleName, funcName, typeArguments = [], args = []) {
for (const client of this.clients) {
try {
const input = {
address: contractAddress,
module: moduleName,
function: funcName,
typeArgs: typeArguments,
args
};
const result = await client.executeViewFunction(input);
return result;
} catch (err) {
await delay(2e3);
console.warn(`Failed to execute view function: ${err}`);
}
}
throw new Error("Failed to execute view function with all fullnodes");
}
async getModuleAbi(accountAddress, moduleName) {
for (const client of this.clients) {
try {
const result = await client.getModuleAbi({
moduleAddr: accountAddress,
moduleName
});
return result;
} catch (err) {
await delay(2e3);
console.warn(
`Failed to get ModuleAbi ${accountAddress} ${moduleName}: ${err}`
);
}
}
throw new Error(
`Failed to get ModuleAbi ${accountAddress} ${moduleName} with all fullnodes`
);
}
async getModuleAbis(accountAddress, modules) {
for (const client of this.clients) {
try {
const result = [];
for (const moduleName of modules) {
const moduleAbi = await client.getModuleAbi({
moduleAddr: accountAddress,
moduleName
});
result.push(moduleAbi);
}
return result;
} catch (err) {
await delay(2e3);
console.warn(
`Failed to get ModuleAbi ${accountAddress} ${modules.join(
","
)}: ${err}`
);
}
}
throw new Error(
`Failed to get ModuleAbi ${accountAddress} ${modules.join(
","
)} with all fullnodes`
);
}
async getBalance(address3, coinType) {
for (const client of this.clients) {
try {
const result = await client.getBalance({
owner: address3,
coinType
});
return result;
} catch (err) {
await delay(2e3);
console.warn(`Failed to get balance: ${err}`);
}
}
throw new Error(`Failed to get balance with all fullnodes`);
}
async getRpcApiVersion() {
for (const client of this.clients) {
try {
const result = await client.getRpcApiVersion();
return result;
} catch (err) {
await delay(2e3);
console.warn(`Failed to get RPC API version: ${err}`);
}
}
throw new Error("Failed to get RPC API version with all fullnodes");
}
async getChainId() {
for (const client of this.clients) {
try {
const result = await client.getChainId();
return result;
} catch (err) {
await delay(2e3);
console.warn(`Failed to get chain ID: ${err}`);
}
}
throw new Error("Failed to get chain ID with all fullnodes");
}
async getStates(params) {
for (const client of this.clients) {
try {
const result = await client.getStates(params);
return result;
} catch (err) {
await delay(2e3);
console.warn(`Failed to get states: ${err}`);
}
}
throw new Error("Failed to get states with all fullnodes");
}
async listStates(params) {
for (const client of this.clients) {
try {
const result = await client.listStates(params);
return result;
} catch (err) {
await delay(2e3);
console.warn(`Failed to list states: ${err}`);
}
}
throw new Error("Failed to list states with all fullnodes");
}
async getEvents(input) {
for (const client of this.clients) {
try {
const result = await client.getEvents(input);
return result;
} catch (err) {
await delay(2e3);
console.warn(`Failed to get events: ${err}`);
}
}
throw new Error("Failed to get events with all fullnodes");
}
async transfer(input) {
for (const client of this.clients) {
try {
const result = await client.transfer(input);
return result;
} catch (err) {
await delay(2e3);
console.warn(`Failed to transfer: ${err}`);
}
}
throw new Error("Failed to transfer with all fullnodes");
}
async transferObject(input) {
for (const client of this.clients) {
try {
const result = await client.transferObject(input);
return result;
} catch (err) {
await delay(2e3);
console.warn(`Failed to transfer object: ${err}`);
}
}
throw new Error("Failed to transfer object with all fullnodes");
}
};
// src/libs/roochContractFactory/index.ts
var RoochContractFactory = class {
/**
* @param packageId
* @param metadata
*/
constructor({ packageId, metadata } = {}) {
this.packageId = packageId || "";
this.metadata = metadata || void 0;
}
};
// src/dubhe.ts
function isUndefined(value) {
return value === void 0;
}
function withMeta(meta, creator) {
creator.meta = meta;
return creator;
}
function createQuery(meta, fn) {
return withMeta(
meta,
async ({
params,
typeArguments
} = {}) => {
const result = await fn(params, typeArguments);
return result;
}
);
}
function createTx(meta, fn) {
return withMeta(
meta,
async ({
tx,
signer,
params,
typeArguments,
isRaw
}) => {
const result = await fn(tx, signer, params, typeArguments, isRaw);
return result;
}
);
}
var _query, _tx, _exec, _read;
var Dubhe = class {
/**
* Support the following ways to init the DubheClient:
* 1. mnemonics
* 2. secretKey (base64 or hex)
* If none of them is provided, will generate a random mnemonics with 24 words.
*
* @param mnemonics, 12 or 24 mnemonics words, separated by space
* @param secretKey, base64 or hex string, when mnemonics is provided, secretKey will be ignored
* @param networkType, 'testnet' | 'mainnet' | 'devnet' | 'localnet', default is 'devnet'
* @param fullnodeUrl, the fullnode url, default is the preconfig fullnode url for the given network type
* @param packageId
*/
constructor({
mnemonics,
secretKey,
networkType,
fullnodeUrls,
packageId,
metadata
} = {}) {
__privateAdd(this, _query, {});
__privateAdd(this, _tx, {});
__privateAdd(this, _exec, async (meta, tx, signer, params, typeArguments, isRaw) => {
if (isRaw === true) {
return tx.callFunction({
target: `${this.contractFactory.packageId}::${meta.moduleName}::${meta.funcName}`,
args: params,
typeArgs: typeArguments
});
}
tx.callFunction({
target: `${this.contractFactory.packageId}::${meta.moduleName}::${meta.funcName}`,
args: params,
typeArgs: typeArguments
});
return await this.signAndExecuteTransaction(tx, signer);
});
__privateAdd(this, _read, async (meta, params, typeArguments) => {
return this.roochInteractor.executeViewFunction(
meta.contractAddress,
meta.moduleName,
meta.funcName,
typeArguments,
params
);
});
this.accountManager = new RoochAccountManager({ mnemonics, secretKey });
fullnodeUrls = fullnodeUrls || [(0, import_rooch_sdk4.getRoochNodeUrl)(networkType ?? "mainnet")];
this.roochInteractor = new RoochInteractor(fullnodeUrls);
this.packageId = packageId;
if (metadata !== void 0) {
this.metadata = metadata;
Object.values(metadata).forEach((metadataRes) => {
let contractAddress = metadataRes.address;
let moduleName = metadataRes.name;
Object.values(metadataRes.functions).forEach((value) => {
const meta = {
contractAddress,
moduleName,
funcName: value.name,
isEntry: value.is_entry,
typeParams: value.type_params,
params: value.params,
return: value.return
};
if (isUndefined(__privateGet(this, _query)[moduleName])) {
__privateGet(this, _query)[moduleName] = {};
}
if (isUndefined(__privateGet(this, _query)[moduleName][value.name])) {
__privateGet(this, _query)[moduleName][value.name] = createQuery(
meta,
(p, type_p) => __privateGet(this, _read).call(this, meta, p, type_p)
);
}
if (isUndefined(__privateGet(this, _tx)[moduleName])) {
__privateGet(this, _tx)[moduleName] = {};
}
if (isUndefined(__privateGet(this, _tx)[moduleName][value.name])) {
__privateGet(this, _tx)[moduleName][value.name] = createTx(
meta,
(tx, s, p, type_p, isRaw) => __privateGet(this, _exec).call(this, meta, tx, s, p, type_p, isRaw)
);
}
});
});
}
this.contractFactory = new RoochContractFactory({
packageId,
metadata
});
}
get query() {
return __privateGet(this, _query);
}
get tx() {
return __privateGet(this, _tx);
}
/**
* if derivePathParams is not provided or mnemonics is empty, it will return the keypair.
* else:
* it will generate signer from the mnemonic with the given derivePathParams.
* @param derivePathParams, such as { accountIndex: 2, isExternal: false, addressIndex: 10 }, comply with the BIP44 standard
*/
getKeypair(derivePathParams) {
return this.accountManager.getKeyPair(derivePathParams);
}
/**
* if derivePathParams is not provided or mnemonics is empty, it will return the currentSigner.
* else:
* it will generate signer from the mnemonic with the given derivePathParams.
* @param derivePathParams, such as { accountIndex: 2, isExternal: false, addressIndex: 10 }, comply with the BIP44 standard
*/
getSigner(derivePathParams) {
const keyPair = this.accountManager.getKeyPair(derivePathParams);
return keyPair;
}
/**
* @description Switch the current account with the given derivePathParams
* @param derivePathParams, such as { accountIndex: 2, isExternal: false, addressIndex: 10 }, comply with the BIP44 standard
*/
switchAccount(derivePathParams) {
this.accountManager.switchAccount(derivePathParams);
}
/**
* @description Get the address of the account for the given derivePathParams
* @param derivePathParams, such as { accountIndex: 2, isExternal: false, addressIndex: 10 }, comply with the BIP44 standard
*/
getBech32Address(derivePathParams) {
return this.accountManager.getAddress(derivePathParams).toBech32Address();
}
getRoochAddress(derivePathParams) {
return this.accountManager.getAddress(derivePathParams);
}
getHexAddress(derivePathParams) {
return this.accountManager.getAddress(derivePathParams).toHexAddress();
}
getBitcoinAddress(derivePathParams) {
return this.accountManager.getBitcoinAddress(derivePathParams);
}
currentAddress() {
return this.accountManager.currentAddress;
}
client() {
return this.roochInteractor.currentClient;
}
getPackageId() {
return this.contractFactory.packageId;
}
getMetadata() {
return this.contractFactory.metadata;
}
getNetwork() {
return this.roochInteractor.network;
}
getFullNodeUrl() {
return this.roochInteractor.currentFullNode;
}
async getRpcApiVersion() {
return this.roochInteractor.getRpcApiVersion();
}
async getChainId() {
return this.roochInteractor.getChainId();
}
async getBalance(accountAddress, coinType, outputOnly) {
try {
if (accountAddress === void 0) {
accountAddress = this.getBech32Address();
}
if (coinType === void 0) {
coinType = "0x3::gas_coin::RGas";
}
const resource = await this.roochInteractor.getBalance(
accountAddress,
coinType
);
return outputOnly ? resource : resource.balance;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : String(err);
throw new Error(
`Failed to get ${coinType} balance for address ${accountAddress}: ${errorMessage}`
);
}
}
async signAndExecuteTransaction(transaction, signer, derivePathParams) {
if (signer === void 0) {
signer = this.getSigner(derivePathParams);
}
return this.roochInteractor.signAndExecuteTransaction(transaction, signer, {
withOutput: true
});
}
async signAndSendTransaction(tx, derivePathParams) {
const sender = this.getSigner(derivePathParams);
return this.signAndExecuteTransaction(tx, sender);
}
async createSession(sessionArgs, signer, derivePathParams) {
if (signer === void 0) {
signer = this.getSigner(derivePathParams);
}
return this.roochInteractor.createSession(sessionArgs, signer);
}
async moveCall(callParams) {
const {
target,
params = [],
typeArguments = [],
signer,
derivePathParams
} = callParams;
const effectiveSigner = signer ?? this.getSigner(derivePathParams);
console.log("effectiveSigner", effectiveSigner.getRoochAddress().toStr());
const tx = new import_rooch_sdk4.Transaction();
tx.callFunction({
target,
args: params,
typeArgs: typeArguments
});
return this.signAndExecuteTransaction(
tx,
effectiveSigner,
derivePathParams
);
}
async publishPackage(callParams) {
const { packageBytes, signer, derivePathParams } = callParams;
return this.moveCall({
target: `0x2::module_store::publish_package_entry`,
params: [import_rooch_sdk4.Args.vec("u8", Array.from(packageBytes))],
signer,
derivePathParams
});
}
async getStates(params) {
return this.roochInteractor.getStates(params);
}
async listStates(params) {
return this.roochInteractor.listStates(params);
}
async getEvents(input) {
return this.roochInteractor.getEvents(input);
}
async transfer(input, signer, derivePathParams) {
if (signer === void 0) {
signer = this.getSigner(derivePathParams);
}
return this.roochInteractor.transfer({
...input,
signer
});
}
async transferObject(input, signer, derivePathParams) {
if (signer === void 0) {
signer = this.getSigner(derivePathParams);
}
return this.roochInteractor.transferObject({
...input,
signer
});
}
};
_query = new WeakMap();
_tx = new WeakMap();
_exec = new WeakMap();
_read = new WeakMap();
// src/metadata/index.ts
var import_rooch_sdk5 = require("@roochnetwork/rooch-sdk");
async function loadMetadata(networkType, packageId, modules, fullnodeUrls) {
fullnodeUrls = fullnodeUrls ?? [(0, import_rooch_sdk5.getRoochNodeUrl)(networkType)];
const roochInteractor = new RoochInteractor(fullnodeUrls);
if (packageId !== void 0) {
const jsonData = await roochInteractor.getModuleAbis(packageId, modules);
return jsonData;
} else {
console.error("please set your package id.");
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Dubhe,
RoochAccountManager,
RoochContractFactory,
RoochInteractor,
loadMetadata,
...require("@roochnetwork/rooch-sdk")
});
//# sourceMappingURL=index.js.map