diff --git a/docs/api/calculate-gas.md b/docs/api/calculate-gas.md index 59bfa978b..7a4b675f4 100644 --- a/docs/api/calculate-gas.md +++ b/docs/api/calculate-gas.md @@ -11,7 +11,7 @@ They guarantee successful message processing and to avoid errors like `Gaslimit ## Calculate gas for messages -To find out the minimum gas amount required to send extrinsic, use `gearApi.program.calculateGas.[method]`. Depending on the conditions, you can calculate gas for initializing a program or processing a message in `handle()` or `reply()`. +To find out the minimum gas amount required to send extrinsic, use `api.program.calculateGas.[method]`. Depending on the conditions, you can calculate gas for initializing a program or processing a message in `handle()` or `reply()`. :::info Gas calculation returns the GasInfo object, which contains 5 parameters: @@ -28,7 +28,7 @@ Gas calculation returns the GasInfo object, which contains 5 parameters: ```javascript const code = fs.readFileSync('demo_ping.opt.wasm'); -const gas = await gearApi.program.calculateGas.initUpload( +const gas = await api.program.calculateGas.initUpload( '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d', // source id code, '0x00', // payload @@ -44,7 +44,7 @@ console.log(gas.toHuman()); ```javascript const codeId = '0x…'; -const gas = await gearApi.program.calculateGas.initCreate( +const gas = await api.program.calculateGas.initCreate( '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d', // source id codeId, '0x00', // payload @@ -59,7 +59,7 @@ console.log(gas.toHuman()); ```javascript import { getProgramMetadata } from '@gear-js/api'; const metadata = await getProgramMetadata('0x' + fs.readFileSync('demo_new_meta.meta.txt')); -const gas = await gearApi.program.calculateGas.handle( +const gas = await api.program.calculateGas.handle( '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d', // source id '0xa178362715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d', // program id { @@ -80,7 +80,7 @@ console.log(gas.toHuman()); ```javascript import { getProgramMetadata } from '@gear-js/api'; const metadata = await getProgramMetadata('0x' + fs.readFileSync('demo_async.meta.txt')); -const gas = await gearApi.program.calculateGas.reply( +const gas = await api.program.calculateGas.reply( '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d', // source id '0x518e6bc03d274aadb3454f566f634bc2b6aef9ae6faeb832c18ae8300fd72635', // message id 'PONG', // payload diff --git a/docs/api/events.md b/docs/api/events.md index d6efed33c..51a4e626f 100644 --- a/docs/api/events.md +++ b/docs/api/events.md @@ -10,7 +10,7 @@ Events are generated for certain operations during execution. The following sect To subscribe to all events: ```javascript -const unsub = await gearApi.query.system.events((events) => { +const unsub = await api.query.system.events((events) => { console.log(events.toHuman()); }); // Unsubscribe @@ -183,15 +183,15 @@ ProgramResumeSessionStarted { ## Check what the event is ```javascript -gearApi.query.system.events((events) => { +api.query.system.events((events) => { events - .filter(({ event }) => gearApi.events.gear.MessageQueued.is(event)) + .filter(({ event }) => api.events.gear.MessageQueued.is(event)) .forEach(({ event: { data } }) => { console.log(data.toHuman()); }); events - .filter(({ event }) => gearApi.events.balances.Transfer.is(event)) + .filter(({ event }) => api.events.balances.Transfer.is(event)) .forEach(({ event: { data } }) => { console.log(data.toHuman()); }); @@ -246,7 +246,7 @@ unsub(); ### Subscribe to Transfer events ```javascript -const unsub = await gearApi.gearEvents.subscribeToTransferEvents( +const unsub = await api.gearEvents.subscribeToTransferEvents( ({ data: { from, to, amount } }) => { console.log(` Transfer balance: @@ -263,7 +263,7 @@ unsub(); ### Subscribe to new blocks ```javascript -const unsub = await gearApi.gearEvents.subscribeToNewBlocks((header) => { +const unsub = await api.gearEvents.subscribeToNewBlocks((header) => { console.log( `New block with number: ${header.number.toNumber()} and hash: ${header.hash.toHex()}`, ); diff --git a/docs/api/extra-queries.md b/docs/api/extra-queries.md index 301390cd4..16cbceb26 100644 --- a/docs/api/extra-queries.md +++ b/docs/api/extra-queries.md @@ -10,35 +10,35 @@ Here is collected a set of useful code snippets in a question-answer format: ### Get block data ```javascript -const data = await gearApi.blocks.get(blockNumberOrBlockHash); +const data = await api.blocks.get(blockNumberOrBlockHash); console.log(data.toHuman()); ``` ### Get block timestamp ```javascript -const ts = await gearApi.blocks.getBlockTimestamp(blockNumberOrBlockHash); +const ts = await api.blocks.getBlockTimestamp(blockNumberOrBlockHash); console.log(ts.toNumber()); ``` ### Get blockHash by block number ```javascript -const hash = await gearApi.blocks.getBlockHash(blockNumber); +const hash = await api.blocks.getBlockHash(blockNumber); console.log(hash.toHex()); ``` ### Get block number by blockhash ```javascript -const hash = await gearApi.blocks.getBlockNumber(blockHash); +const hash = await api.blocks.getBlockNumber(blockHash); console.log(hash.toNumber()); ``` ### Get all block's events ```javascript -const events = await gearApi.blocks.getEvents(blockHash); +const events = await api.blocks.getEvents(blockHash); events.forEach((event) => { console.log(event.toHuman()); }); @@ -47,7 +47,7 @@ events.forEach((event) => { ### Get all block's extrinsics ```javascript -const extrinsics = await gearApi.blocks.getExtrinsics(blockHash); +const extrinsics = await api.blocks.getExtrinsics(blockHash); extrinsics.forEach((extrinsic) => { console.log(extrinsic.toHuman()); }); @@ -56,10 +56,10 @@ extrinsics.forEach((extrinsic) => { ## Get transaction fee ```javascript -const gearApi = await GearApi.create(); -gearApi.program.submit({ code, gasLimit }); -// same for gearApi.message, gearApi.reply and others -const paymentInfo = await gearApi.program.paymentInfo(alice); +const api = await GearApi.create(); +api.program.submit({ code, gasLimit }); +// same for api.message, api.reply and others +const paymentInfo = await api.program.paymentInfo(alice); const transactionFee = paymentInfo.partialFee.toNumber(); consolg.log(transactionFee); ``` diff --git a/docs/api/mailbox.md b/docs/api/mailbox.md index eb0cf38e5..b18b600a3 100644 --- a/docs/api/mailbox.md +++ b/docs/api/mailbox.md @@ -10,8 +10,8 @@ The mailbox contains messages from the program that are waiting for user action. ## Read messages from Mailbox ```javascript -const gearApi = await GearApi.create(); -const mailbox = await gearApi.mailbox.read( +const api = await GearApi.create(); +const mailbox = await api.mailbox.read( '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', ); console.log(mailbox); @@ -19,21 +19,21 @@ console.log(mailbox); ## Claim value -To claim value from a message in the mailbox use `GearApi.mailbox.claimValue.submit` method. +To claim value from a message in the mailbox use `api.mailbox.claimValue.submit` method. ```javascript -const gearApi = await GearApi.create(); -const submitted = await gearApi.mailbox.claimValue.submit(messageId); -await gearApi.mailbox.claimValue.signAndSend(/* ... */); +const api = await GearApi.create(); +const submitted = await api.mailbox.claimValue.submit(messageId); +await api.mailbox.claimValue.signAndSend(/* ... */); ``` ## Waitlist -To read the program's waitlist use `GearApi.waitlist.read` method. +To read the program's waitlist use `api.waitlist.read` method. ```javascript -const gearApi = await GearApi.create(); +const api = await GearApi.create(); const programId = '0x1234…'; -const waitlist = await gearApi.waitlist.read(programId); +const waitlist = await api.waitlist.read(programId); console.log(waitlist); ``` diff --git a/docs/api/program-rent.md b/docs/api/program-rent.md new file mode 100644 index 000000000..ac7ad3aea --- /dev/null +++ b/docs/api/program-rent.md @@ -0,0 +1,64 @@ +--- +sidebar_position: 5 +sidebar_label: Pay Program rent +--- + +To pay program rent, use the following JavaScript code: + +```javascript + +// program.payRent has params: +// programId +// blockCount - number of blocks for which we want to extend +const tx = await api.program.payRent('0x...', 100_000); + +tx.signAndSend(account, (events) => { + events.forEach(({ event }) => console.log(event.toHuman())); +}); + +``` + +You can calculate the current rent price using the following code: + +```javascript + +const price = api.program.calculatePayRent(blockCount); + +``` + +If a program was paused and its pages removed from storage, you can restore it using the `api.program.resumeSession` methods: + +- `init`: Start a new session to resume the program. +- `push`: Push a bunch of program pages. +- `commit`: Finish the resume session. + +Here's how you can resume a paused program: + +```javascript + +const program = await api.programStorage.getProgram(programId, oneBlockBeforePauseHash); +const initTx = api.program.resumeSession.init({ + programId, + allocations: program.allocations, + codeHash: program.codeHash.toHex(), +}); + +let sessionId; +initTx.signAndSend(account, ({ events }) => { + events.forEach(({ event: { method, data } }) => { + if (method === 'ProgramResumeSessionStarted') { + sessionId = data.sessionId.toNumber(); + } + }); +}); + +const pages = await api.programStorage.getProgramPages(programId, program, oneBlockBeforePauseHash); +for (const memPage of Object.entries(page)) { + const tx = api.program.resumeSession.push({ sessionId, memoryPages: [memPage] }); + tx.signAndSend(account); +} + +const tx = api.program.resumeSession.commit({ sessionId, blockCount: 20_000 }); +tx.signAndSend(account); + +``` diff --git a/docs/api/read-state.md b/docs/api/read-state.md index 1d1c75bf3..2476fbd8f 100644 --- a/docs/api/read-state.md +++ b/docs/api/read-state.md @@ -7,26 +7,26 @@ sidebar_label: Read State There are two different ways to query the program `State`: -1. Query the full `State` of the program. To read the full `State` of the program, you need to have only the `metadata` of this program. You can call `gearApi.programState.read` method to get the state. +1. Query the full `State` of the program. To read the full `State` of the program, you need to have only the `metadata` of this program. You can call `api.programState.read` method to get the state. ```javascript import { GearApi } from '@gear-js/api'; -const gearApi = await GearApi.create({ +const api = await GearApi.create({ providerAddress: 'wss://testnet.vara.rs', }); -await gearApi.programState.read({ programId: '0x…' }, programMetadata); +await api.programState.read({ programId: '0x…' }, programMetadata); ``` Also, you can read the `State` of the program at some specific block specified by its hash: ```javascript -await gearApi.programState.read( +await api.programState.read( { programId: '0x…', at: '0x…' }, programMetadata, ); ``` -2. If you are using the custom functions to query only specific parts of the program State ([see more](/docs/developing-contracts/metadata#genarate-metadata)), then you should call `GearApi.programState.readUsingWasm` method: +2. If you are using the custom functions to query only specific parts of the program State ([see more](/docs/developing-contracts/metadata#genarate-metadata)), then you should call `api.programState.readUsingWasm` method: ```js // ... @@ -34,7 +34,7 @@ import { getStateMetadata } from '@gear-js/api'; const stateWasm = readFileSync('path/to/state.meta.wasm'); const metadata = await getStateMetadata(stateWasm); -const state = await gearApi.programState.readUsingWasm( +const state = await api.programState.readUsingWasm( { programId: '0x…', fn_name: 'name_of_function_to_execute', @@ -58,13 +58,13 @@ const buffer = await Buffer.from(arrayBuffer); const metadata = await getStateMetadata(buffer); // get State only of the first wallet -const firstState = await gearApi.programState.readUsingWasm( +const firstState = await api.programState.readUsingWasm( { programId: '0x…', fn_name: 'first_wallet', buffer }, metadata, ); // get wallet State by id -const secondState = await gearApi.programState.readUsingWasm( +const secondState = await api.programState.readUsingWasm( { programId: '0x…', fn_name: 'wallet_by_id', buffer, argument: { decimal: 1, hex: '0x01' } }, metadata, ); diff --git a/docs/api/send-message.mdx b/docs/api/send-message.mdx index 880c9eed4..feea9d6a9 100644 --- a/docs/api/send-message.mdx +++ b/docs/api/send-message.mdx @@ -5,7 +5,7 @@ sidebar_label: Send Message # Send Message -Use `GearApi.message.send` method to send messages to the program: +Use `api.message.send` method to send messages to the program: ```javascript try { @@ -16,9 +16,9 @@ try { value: 1000, }; // In that case payload will be encoded using meta.types.handle.input type - let extrinsic = gearApi.message.send(message, meta); + let extrinsic = api.message.send(message, meta); // So if you want to use another type you can specify it - extrinsic = gearApi.message.send(message, meta, meta.types.other.input); + extrinsic = api.message.send(message, meta, meta.types.other.input); } catch (error) { console.error(`${error.name}: ${error.message}`); } @@ -33,14 +33,14 @@ try { :::note -In real conditions to ensure successful message processing, the calculation of the required gas for processing the message should be performed by using `GearApi.program.calculateGas` method. +In real conditions to ensure successful message processing, the calculation of the required gas for processing the message should be performed by using `api.program.calculateGas` method. [more info](/docs/api/calculate-gas) ::: ### Send reply message -When you need to reply to a message received from a program, use `GearApi.message.reply`: +When you need to reply to a message received from a program, use `api.message.reply`: ```javascript try { @@ -51,7 +51,7 @@ try { value: 1000, }; // In this case payload will be encoded using `meta.types.reply.input` type. - const extrinsic = gearApi.message.sendReply(reply, meta); + const extrinsic = api.message.sendReply(reply, meta); } catch (error) { console.error(`${error.name}: ${error.message}`); } diff --git a/docs/api/submit-code.md b/docs/api/submit-code.md index f13c6f036..81d193bf5 100644 --- a/docs/api/submit-code.md +++ b/docs/api/submit-code.md @@ -10,9 +10,9 @@ If you need to load the program code into the chain without initialization use ` ```javascript const code = fs.readFileSync('path/to/program.opt.wasm'); -const { codeHash } = await gearApi.code.upload(code); +const { codeHash } = await api.code.upload(code); -gearApi.code.signAndSend(alice, () => { +api.code.signAndSend(alice, () => { events.forEach(({ event: { method, data } }) => { if (method === 'ExtrinsicFailed') { throw new Error(data.toString()); @@ -25,7 +25,7 @@ gearApi.code.signAndSend(alice, () => { ## Create program from uploaded code on chain -Use `GearApi.program.create` method to create `create_program` extrinsic: +Use `api.program.create` method to create `create_program` extrinsic: ```javascript const codeId = '0x…'; @@ -37,7 +37,7 @@ const program = { initPayload: somePayload, }; -const { programId, salt, extrinsic } = gearApi.program.create(program, meta); +const { programId, salt, extrinsic } = api.program.create(program, meta); await extrinsic.signAndSend(keyring, (event) => { console.log(event.toHuman()); diff --git a/docs/api/upload-program.md b/docs/api/upload-program.md index 2896a4ee1..f6d0b37db 100644 --- a/docs/api/upload-program.md +++ b/docs/api/upload-program.md @@ -7,7 +7,7 @@ sidebar_label: Upload Program A smart contract compiled to Wasm can be uploaded to the Gear network as a program. During uploading it is initialized in the network to be able to send and receive messages with other actors in the network (programs and users). -Use `GearApi.program.upload` method to create `upload_program` extrinsic +Use `api.program.upload` method to create `upload_program` extrinsic ```javascript const code = fs.readFileSync('path/to/program.wasm'); @@ -20,7 +20,7 @@ const program = { }; try { - const { programId, codeId, salt, extrinsic } = gearApi.program.upload( + const { programId, codeId, salt, extrinsic } = api.program.upload( program, meta, ); @@ -39,7 +39,7 @@ try { :::note -For the calculation of the required gas for `init` message processing should use `GearApi.program.calculateGas.initUpload()` method. +For the calculation of the required gas for `init` message processing should use `api.program.calculateGas.initUpload()` method. [more info](/docs/api/calculate-gas) ::: diff --git a/docs/developing-contracts/rent-system.md b/docs/developing-contracts/rent-system.md new file mode 100644 index 000000000..3c980c024 --- /dev/null +++ b/docs/developing-contracts/rent-system.md @@ -0,0 +1,42 @@ +--- +sidebar_label: Program Rent +sidebar_position: 12 +--- + +# Program Rent + +Gear Protocol utilizes a rent-based program management system. When developers upload a program (smart contract) to the network, its expiration date is assigned. The expiration period is measured in blocks. + +After the expiration date, the program is automatically removed from storage, unless the owner chooses to extend its life by paying rent. The owner must indicate the number of additional blocks they can pay for, and they need to pay the rent in utility tokens to keep the program active beyond its initial expiration date. + +:::info +Current initial rent period: ***5,000,000*** blocks (on Vara it will be around 173 days) +::: + +After uploading a program, you can observe a similar event: + +`gear.ProgramChanged` + +```json +{ + "id": "0xde76e4cf663ff825d94944d6f060204e83fbb5e24f8dfdbbdc25842df4f4135d", + "change": { + "Active": { + "expiration": "12,834,248" + } + } +} +``` + +## How to extend the rent of the program? + +To extend the rent period of a program, simply call the special extrinsic `gear.payProgramRent(programId, blockCount)`. [See more](/docs/api/program-rent) + +## Can I restore a deleted program? + +Yes. Since the blockchain stores all states for the entire history, you can restore the program's state to the previous block before it was deleted. + +## Why does Gear use the program rent system? + +- Optimization and efficient resource usage +- Stimulating utility token usage