@gear-js/api
Version:
A JavaScript library that provides functionality to connect GEAR Component APIs.
168 lines (164 loc) • 6.27 kB
JavaScript
'use strict';
var utilCrypto = require('@polkadot/util-crypto');
var program_errors = require('../errors/program.errors.js');
require('@polkadot/util');
var generate = require('../utils/generate.js');
var prefixes = require('../utils/prefixes.js');
var validate = require('../utils/validate.js');
require('@polkadot/api');
var createPayload = require('../utils/create-payload.js');
var getExtrinsic = require('../utils/getExtrinsic.js');
var Gas = require('./Gas.js');
var Transaction = require('./Transaction.js');
class GearProgram extends Transaction.GearTransaction {
_api;
calculateGas;
// public resumeSession: GearResumeSession;
constructor(_api) {
super(_api);
this._api = _api;
this.calculateGas = new Gas.GearGas(_api);
// this.resumeSession = new GearResumeSession(_api);
}
upload(args, metaOrHexRegistry, typeIndexOrTypeName) {
validate.validateValue(args.value, this._api);
validate.validateGasLimit(args.gasLimit, this._api);
const salt = args.salt || utilCrypto.randomAsHex(20);
const code = typeof args.code === 'string' ? args.code : this._api.createType('Bytes', Array.from(args.code));
const payload = createPayload.encodePayload(args.initPayload, metaOrHexRegistry, 'init', typeIndexOrTypeName);
const codeId = generate.generateCodeHash(code);
const programId = generate.generateProgramId(codeId, salt);
try {
const txArgs = [code, salt, payload, args.gasLimit, args.value || 0, args.keepAlive];
this.extrinsic = getExtrinsic.getExtrinsic(this._api, 'gear', 'uploadProgram', txArgs);
return { programId, codeId, salt, extrinsic: this.extrinsic };
}
catch (error) {
console.log(error);
throw new program_errors.SubmitProgramError();
}
}
create({ codeId, initPayload, value, gasLimit, ...args }, metaOrHexRegistry, typeIndexOrTypeName) {
validate.validateValue(value, this._api);
validate.validateGasLimit(gasLimit, this._api);
const payload = createPayload.encodePayload(initPayload, metaOrHexRegistry, 'init', typeIndexOrTypeName);
const salt = args.salt || utilCrypto.randomAsHex(20);
const programId = generate.generateProgramId(codeId, salt);
try {
const txArgs = [codeId, salt, payload, gasLimit, value || 0, args.keepAlive];
this.extrinsic = getExtrinsic.getExtrinsic(this._api, 'gear', 'createProgram', txArgs);
return { programId, salt, extrinsic: this.extrinsic };
}
catch (_) {
throw new program_errors.SubmitProgramError();
}
}
/**
* ### Pay program rent
* @param programId
* @param blockCount
* @returns
* @example
* ```javascript
* const tx = await api.program.payRent('0x...', 100_000);
* tx.signAndSend(account, (events) => {
* events.forEach(({event}) => console.log(event.toHuman()))
* })
* ```
*/
async payRent(programId, blockCount) {
await validate.validateProgramId(programId, this._api);
return this._api.tx.gear.payProgramRent(programId, blockCount);
}
/**
* ### Calculate the cost of rent for a certain number of blocks
* @param blockCount
* @returns u128 number
*/
calcualtePayRent(blockCount) {
return this.costPerBlock.muln(blockCount);
}
/**
* Get ids of all uploaded programs
* @returns Array of program ids
*/
async allUploadedPrograms(count) {
const prefix = this._api.query.gearProgram.programStorage.keyPrefix();
const programIds = [];
if (count) {
const keys = await this._api.rpc.state.getKeysPaged(prefix, count);
programIds.push(...prefixes.getIdsFromKeys(keys, prefix));
}
else {
count = 1000;
const keys = await this._api.rpc.state.getKeysPaged(prefix, count);
programIds.push(...prefixes.getIdsFromKeys(keys, prefix));
let keysLength = keys.length;
let lastKey = keys.at(-1);
while (keysLength === count) {
const keys = await this._api.rpc.state.getKeysPaged(prefix, count, lastKey);
programIds.push(...prefixes.getIdsFromKeys(keys, prefix));
lastKey = keys.at(-1);
keysLength = keys.length;
}
}
return programIds;
}
/**
*
* @param id A program id
* @returns `true` if address belongs to program, and `false` otherwise
*/
async exists(id) {
const program = (await this._api.query.gearProgram.programStorage(id));
return program.isSome;
}
/**
* @deprecated use `api.program.codeId` instead
*/
async codeHash(id) {
return this.codeId(id);
}
/**
* Get code's id of the program uploaded on chain
* @param programId
* @returns codeId of the program code
*/
async codeId(id) {
const program = await this._api.programStorage.getProgram(id);
return program.codeId.toHex();
}
/**
* ### Get hash of program metadata
* @param programId
* @param at (optional) block hash
* @returns
*/
async metaHash(programId, at) {
try {
const metaHash = (await this._api.rpc.gear.readMetahash(programId, at || null));
return metaHash.toHex();
}
catch (error) {
if (error.code === 8000) {
if (error.data.includes('Program not found')) {
throw new program_errors.ProgramDoesNotExistError(programId);
}
if (error.data.includes('unreachable')) {
throw new program_errors.ProgramHasNoMetahash(programId);
}
}
throw error;
}
}
get costPerBlock() {
return this._api.consts.gear.programRentCostPerBlock;
}
get rentMinimalResumePeriod() {
return this._api.consts.gear.programRentMinimalResumePeriod;
}
get rentFreePeriod() {
return this._api.consts.gear.programRentFreePeriod;
}
}
exports.GearProgram = GearProgram;