@massalabs/massa-web3
Version:
massa's web3 sdk client
273 lines • 11.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Web3Provider = exports.JsonRpcProvider = void 0;
const __1 = require("../..");
const generated_1 = require("../../generated");
const operation_1 = require("../../operation");
const operationManager_1 = require("../../operation/operationManager");
const bytecode_1 = require("../../basicElements/bytecode");
const errors_1 = require("../../errors");
const jsonRpcPublicProvider_1 = require("./jsonRpcPublicProvider");
class JsonRpcProvider extends jsonRpcPublicProvider_1.JsonRpcPublicProvider {
client;
account;
constructor(client, account) {
super(client);
this.client = client;
this.account = account;
}
static fromRPCUrl(url, account) {
const client = new __1.PublicAPI(url);
if (account) {
return new JsonRpcProvider(client, account);
}
return new jsonRpcPublicProvider_1.JsonRpcPublicProvider(client);
}
static mainnet(account) {
return account
? JsonRpcProvider.fromRPCUrl(__1.PublicApiUrl.Mainnet, account)
: JsonRpcProvider.fromRPCUrl(__1.PublicApiUrl.Mainnet);
}
static buildnet(account) {
return account
? JsonRpcProvider.fromRPCUrl(__1.PublicApiUrl.Buildnet, account)
: JsonRpcProvider.fromRPCUrl(__1.PublicApiUrl.Buildnet);
}
// eslint-disable-next-line @typescript-eslint/naming-convention
_providerName = 'Massa Json Rpc provider';
get accountName() {
return this.account.address.toString();
}
get providerName() {
return this._providerName;
}
get address() {
return this.account.address.toString();
}
async balance(final = true) {
return this.client.getBalance(this.address.toString(), final);
}
async rollOperation(type, amount, opts) {
if (type !== operation_1.OperationType.RollBuy && type !== operation_1.OperationType.RollSell) {
throw new Error('Invalid roll operation type.');
}
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
if (amount <= 0) {
throw new Error('amount of rolls must be a positive non-zero value.');
}
const operation = new operationManager_1.OperationManager(this.account.privateKey, this.client);
const details = {
fee: opts?.fee ?? (await this.client.getMinimalFee()),
expirePeriod: await (0, operationManager_1.getAbsoluteExpirePeriod)(this.client, opts?.periodToLive),
type,
amount,
};
const operationId = await operation.send(details);
return new operation_1.Operation(this, operationId);
}
/**
* Buys rolls.
*
* @param amount - The number of rolls to buy.
* @param opts - Optional operation details.
*
* @returns The ID of the operation.
* @throws If the amount of rolls is not a positive non-zero value.
*/
async buyRolls(amount, opts) {
return this.rollOperation(operation_1.OperationType.RollBuy, amount, opts);
}
/**
* Sells rolls.
*
* @param amount - The number of rolls to sell.
* @param opts - Optional operation details.
*
* @returns The ID of the operation.
* @throws If the amount of rolls is not a positive non-zero value.
*/
async sellRolls(amount, opts) {
return this.rollOperation(operation_1.OperationType.RollSell, amount, opts);
}
/**
* Transfers tokens.
*
* @param to - The address of the recipient.
* @param amount - The amount of tokens to transfer.
* @param opts - Optional operation details.
*
* @returns The ID of the operation.
* @throws If the amount of tokens is not a positive non-zero value.
*/
async transfer(to, amount, opts) {
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
if (amount <= 0) {
throw new Error('amount to transfer must be a positive non-zero value.');
}
if (typeof to === 'string') {
to = __1.Address.fromString(to);
}
const operation = new operationManager_1.OperationManager(this.account.privateKey, this.client);
const details = {
fee: opts?.fee ?? (await this.client.getMinimalFee()),
expirePeriod: await (0, operationManager_1.getAbsoluteExpirePeriod)(this.client, opts?.periodToLive),
type: operation_1.OperationType.Transaction,
amount,
recipientAddress: to,
};
const operationId = await operation.send(details);
return new operation_1.Operation(this, operationId);
}
async sign(data) {
const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data;
const sig = await this.account.sign(bytes);
return {
publicKey: this.account.publicKey.toString(),
signature: sig.toString(),
};
}
async callSC(params) {
const operationId = await this.call(params);
return new operation_1.Operation(this, operationId);
}
/**
* Executes Binary Smart Contract Code Onchain
*
* Executes a binary code (smart contract) directly on the blockchain without deploying or storing it.
* This function is particularly useful for one-off actions or tasks that require blockchain execution
* but do not need the persistence or state of a deployed smart contract.
*
* @remarks
* If the execution involves storing data or spending coins, the sender's address (i.e., the user's address
* initiating the contract execution) will be used.
*
* @see {@link https://docs.massa.net/docs/learn/operation-format-execution#executesc-operation-payload} for more details
* on the setup and usage of the datastore during execution.
*/
async executeSC(params) {
return new operation_1.Operation(this, await this.executeSc(params));
}
async deploySC(params) {
const operationId = await this.deploy(params);
const operation = new operation_1.Operation(this, operationId);
const deployedAddress = await operation.getDeployedAddress(params.waitFinalExecution);
return new __1.SmartContract(this, deployedAddress);
}
/**
* Executes Binary Smart Contract Code Onchain.
* @see {@link https://docs.massa.net/docs/learn/operation-format-execution#executesc-operation-payload} for more information on how to setup datastore.
*/
async executeSc(params) {
return (0, bytecode_1.execute)(this.client, this.account.privateKey, params.byteCode, {
fee: params.fee,
periodToLive: params.periodToLive,
maxCoins: params.maxCoins,
maxGas: params.maxGas,
datastore: params.datastore,
});
}
/**
* Executes a smart contract call operation
* @param params - callSCParams.
* @returns A promise that resolves to an Operation object representing the transaction.
*/
async call(params) {
const coins = params.coins ?? 0n;
await this.checkAccountBalance(coins);
const args = params.parameter ?? new Uint8Array();
const parameter = args instanceof Uint8Array ? args : args.serialize();
const fee = params.fee ?? (await this.client.getMinimalFee());
let maxGas = params.maxGas;
if (!maxGas) {
maxGas = await this.getGasEstimation(params);
}
else {
if (maxGas > __1.MAX_GAS_CALL) {
throw new errors_1.ErrorMaxGas({ isHigher: true, amount: __1.MAX_GAS_CALL });
}
else if (maxGas < __1.MIN_GAS_CALL) {
throw new errors_1.ErrorMaxGas({ isHigher: false, amount: __1.MIN_GAS_CALL });
}
}
const details = {
fee,
expirePeriod: await (0, operationManager_1.getAbsoluteExpirePeriod)(this.client, params.periodToLive),
type: operation_1.OperationType.CallSmartContractFunction,
coins,
maxGas,
address: params.target,
func: params.func,
parameter,
};
const manager = new operationManager_1.OperationManager(this.account.privateKey, this.client);
return manager.send(details);
}
async checkAccountBalance(coins) {
if (coins > 0n) {
const balance = await this.client.getBalance(this.account.address.toString());
if (balance < coins) {
throw new errors_1.ErrorInsufficientBalance({
userBalance: balance,
neededBalance: coins,
});
}
}
}
/**
* Deploys a smart contract on the blockchain.
*
* @param params - Optional deployment details with defaults as follows:
* @param params.fee - Execution fee, auto-estimated if absent.
* @param params.maxCoins - Maximum number of coins to use, auto-estimated if absent.
* @param params.maxGas - Maximum execution gas, auto-estimated if absent.
* @param params.periodToLive - Duration in blocks before the transaction expires, defaults to 10.
*
* @returns The deployed smart contract.
*
* @throws If the account has insufficient balance to deploy the smart contract.
*/
async deploy(params) {
const coins = params.coins ?? 0n;
const totalCost = __1.StorageCost.smartContractDeploy(params.byteCode.length) + coins;
await this.checkAccountBalance(totalCost);
const args = params.parameter ?? new Uint8Array();
const parameter = args instanceof Uint8Array ? args : args.serialize();
const datastore = (0, __1.populateDatastore)([
{
data: params.byteCode,
args: parameter,
coins,
},
]);
const fee = params.fee ?? (await this.client.getMinimalFee());
return (0, bytecode_1.execute)(this.client, this.account.privateKey, generated_1.DEPLOYER_BYTECODE, {
fee,
periodToLive: params.periodToLive,
maxCoins: params?.maxCoins ?? totalCost,
maxGas: params.maxGas,
datastore,
});
}
/**
* Reads smart contract function.
* @param params - readSCParams.
* @returns A promise that resolves to a ReadSCData.
*/
async readSC(params) {
const args = params.parameter ?? new Uint8Array();
const caller = params.caller ?? this.account.address.toString();
const readOnlyParams = {
...params,
caller,
parameter: args instanceof Uint8Array ? args : args.serialize(),
};
return this.client.executeReadOnlyCall(readOnlyParams);
}
async getGasEstimation(params) {
const caller = params.caller ?? this.account.address.toString();
return super.getGasEstimation({ ...params, caller });
}
}
exports.JsonRpcProvider = JsonRpcProvider;
exports.Web3Provider = JsonRpcProvider;
//# sourceMappingURL=jsonRpcProvider.js.map