UNPKG

@gear-js/api

Version:

A JavaScript library that provides functionality to connect GEAR Component APIs.

168 lines (164 loc) 6.27 kB
'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;