UNPKG

@gear-js/api

Version:

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

143 lines (140 loc) 5.72 kB
import { ReplaySubject } from 'rxjs'; import { SendMessageError, SendReplyError } from '../errors/message.errors.js'; import '@polkadot/util'; import '../utils/generate.js'; import { validateValue, validateGasLimit, validateMailboxItem } from '../utils/validate.js'; import { decodeAddress } from '../utils/address.js'; import '@polkadot/util-crypto'; import { encodePayload } from '../utils/create-payload.js'; import { getExtrinsic } from '../utils/getExtrinsic.js'; import { GearTransaction } from './Transaction.js'; class GearMessage extends GearTransaction { /** * ## Send Message * @param message * @param metaOrHexRegistry Metadata * @param typeIndexOrTypeName type index in registry or type name * @returns Submitable result */ send({ destination, value, gasLimit, payload, keepAlive }, metaOrHexRegistry, typeIndexOrTypeName) { validateValue(value, this._api); validateGasLimit(gasLimit, this._api); const _payload = encodePayload(payload, metaOrHexRegistry, 'handle', typeIndexOrTypeName); try { const txArgs = [destination, _payload, gasLimit, value || 0, keepAlive || true]; this.extrinsic = getExtrinsic(this._api, 'gear', 'sendMessage', txArgs); return this.extrinsic; } catch (error) { throw new SendMessageError(error.message); } } /** * Sends reply message * @param args Message parameters * @param metaOrHexRegistry Metadata * @param typeIndexOrTypeName type index in registry or type name * @returns Submittable result */ async sendReply({ value, gasLimit, replyToId, payload, account, keepAlive }, metaOrHexRegistry, typeIndexOrTypeName) { validateValue(value, this._api); validateGasLimit(gasLimit, this._api); if (account) { await validateMailboxItem(account, replyToId, this._api); } const _payload = encodePayload(payload, metaOrHexRegistry, 'reply', typeIndexOrTypeName); try { const txArgs = [replyToId, _payload, gasLimit, value || 0, keepAlive || true]; this.extrinsic = getExtrinsic(this._api, 'gear', 'sendReply', txArgs); return this.extrinsic; } catch (_) { throw new SendReplyError(); } } /** * ## Get event with reply message * @param msgId - id of sent message * @param txBlock - number or hash of block where the message was sent * @returns UserMessageSent event */ async getReplyEvent(programId, msgId, txBlock) { let unsub; const replyEvent = new Promise((resolve) => { unsub = this._api.gearEvents.subscribeToGearEvent('UserMessageSent', (event) => { if (event.data.message.source.eq(programId) === false) return; if (msgId === null) { resolve(event); } if (event.data.message.details.isSome && event.data.message.details.unwrap().to.toHex() === msgId) { resolve(event); } }, txBlock); }); (await unsub)(); return replyEvent; } /** * @deprecated Use `getReplyEvent` instead */ listenToReplies(programId, bufferSize = 5) { let unsub; const subject = new ReplaySubject(bufferSize); this._api.gearEvents .subscribeToGearEvent('UserMessageSent', ({ data }) => { if (data.message.source.eq(programId)) { if (data.message.details.isSome) { data.message.details.unwrap().to.toHex(); { subject.next([data.message.details.unwrap().to.toHex(), data]); } } } }) .then((result) => { unsub = result; }); return (messageId) => { return new Promise((resolve) => { subject.subscribe({ next: ([id, data]) => { if (id === messageId) { subject.complete(); unsub(); resolve(data); } }, }); }); }; } /** * ## Send message to the program and get the reply. * This method is immutable and doesn't send any extrinsic. * @param params Message parameters * @param meta (optional) Program metadata obtained using `ProgramMetadata.from` method. * @param typeIndexOrTypeName (optional) Index of type in the registry. If not specified the type index from `meta.handle.input` will be used instead. * @returns Reply info structure * * @example * ```javascript * const programId = '0x..'; * const origin = '0x...'; * const meta = ProgramMetadata.from('0x...'); * const result = await api.message.calculateReply({ * origin, * destination: programId, * payload: { myPayload: [] }, * value: 0 * }, meta); * * console.log(result.toJSON()); * console.log('reply payload:', meta.createType(meta.types.handle.output, result.payload).toJSON()); */ async calculateReply({ payload, origin, destination, value, gasLimit, at }, meta, typeIndexOrTypeName) { const _payload = encodePayload(payload, meta, 'handle', typeIndexOrTypeName); return await this._api.rpc.gear.calculateReplyForHandle(decodeAddress(origin), destination, _payload, gasLimit || this._api.blockGasLimit.toBigInt(), value || 0, at || null); } } export { GearMessage };