diff --git a/docs/staking-api/cosmos/_category_.json b/docs/staking-api/cosmos/_category_.json index e2e26fd..ef1dc79 100644 --- a/docs/staking-api/cosmos/_category_.json +++ b/docs/staking-api/cosmos/_category_.json @@ -1,6 +1,5 @@ { "label": "Cosmos", - "position": 5, "link": { "type": "generated-index", "description": "Staking API Cosmos Hub documentation" diff --git a/docs/staking-api/ethereum/_category_.json b/docs/staking-api/ethereum/_category_.json index 3a7a151..5331594 100644 --- a/docs/staking-api/ethereum/_category_.json +++ b/docs/staking-api/ethereum/_category_.json @@ -1,6 +1,5 @@ { "label": "Ethereum", - "position": 4, "link": { "type": "generated-index", "description": "Staking API Ethereum documentation." diff --git a/docs/staking-api/monad/_category_.json b/docs/staking-api/monad/_category_.json new file mode 100644 index 0000000..715c570 --- /dev/null +++ b/docs/staking-api/monad/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Monad", + "link": { + "type": "generated-index", + "description": "Staking API Monad documentation." + } +} + diff --git a/docs/staking-api/monad/endpoints.md b/docs/staking-api/monad/endpoints.md new file mode 100644 index 0000000..d1baa4b --- /dev/null +++ b/docs/staking-api/monad/endpoints.md @@ -0,0 +1,248 @@ +--- +sidebar_position: 3 +--- +# Endpoints + +import StakingOpenApiLink from '@site/src/components/StakingOpenApiLink'; + +## API Usage +Once you already have access to the Staking API with a validated user and existing apikeys you can start using this service. + +### API Reference docs + +:::tip + +You can check the **Staking API Reference** here: +- Rendered [doc page](/staking-api/api-reference). +- +::: + +## Authentication + +In order to use staking api related endpoints you need to include your **API KEY** + +:::tip + +**Heads up!** +To obtain a valid API key required for authentication, please refer to the [Authentication > Auth](/staking-api/authentication#auth) section of the documentation. + +::: + +**Header:** + +| Name | Description | Example value | Required +| --------------- | ------------ | ------------ |------------ | +| `X-API-KEY` | Your api key value | `` | ✅ | + +____ + +### Delegate action + +Craft a delegate transaction: + +- Endpoint: [`/api/v1/eth/monad/action/delegate`](/staking-api/api-reference#tag/eth-monad/post/api/v1/eth/monad/action/delegate) + +#### Description + +This endpoint will craft a delegate transaction ready to be signed. The transaction will delegate the specified amount to the validator. + +#### Request body parameters + +[`MonadStakeActionDto`](/staking-api/api-reference#model/monadstakeactiondto) + +#### Returned + +[`MonadActionResponseDto`](/staking-api/api-reference#model/monadactionresponsedto) + +____ + +### Undelegate action + +Craft an undelegate transaction: + +- Endpoint: [`/api/v1/eth/monad/action/undelegate`](/staking-api/api-reference#tag/eth-monad/post/api/v1/eth/monad/action/undelegate) + +#### Description + +This endpoint will craft an undelegate transaction ready to be signed. The undelegated amount will be placed in a withdrawal slot and can be withdrawn after the withdrawal epoch. + +#### Request body parameters + +[`MonadUndelegateActionDto`](/staking-api/api-reference#model/monadundelegateactiondto) + +#### Returned + +[`MonadActionResponseDto`](/staking-api/api-reference#model/monadactionresponsedto) + +____ + +### Withdraw action + +Craft a withdraw transaction: + +- Endpoint: [`/api/v1/eth/monad/action/withdraw`](/staking-api/api-reference#tag/eth-monad/post/api/v1/eth/monad/action/withdraw) + +#### Description + +Once the withdrawal is available (after the withdrawal epoch), you can claim it. This action will craft a withdraw transaction for the specified withdrawal slot. + +#### Request body parameters + +[`MonadWithdrawActionDto`](/staking-api/api-reference#model/monadwithdrawactiondto) + +#### Returned + +[`MonadActionResponseDto`](/staking-api/api-reference#model/monadactionresponsedto) + +____ + +### Claim rewards action + +Craft a claim rewards transaction: + +- Endpoint: [`/api/v1/eth/monad/action/claim-rewards`](/staking-api/api-reference#tag/eth-monad/post/api/v1/eth/monad/action/claim-rewards) + +#### Description + +This endpoint will craft a claim rewards transaction ready to be signed. It allows you to claim accumulated staking rewards. + +#### Request body parameters + +[`MonadClaimRewardsActionDto`](/staking-api/api-reference#model/monadclaimrewardsactiondto) + +#### Returned + +[`MonadActionResponseDto`](/staking-api/api-reference#model/monadactionresponsedto) + +____ + +### Compound action + +Craft a compound rewards transaction: + +- Endpoint: [`/api/v1/eth/monad/action/compound`](/staking-api/api-reference#tag/eth-monad/post/api/v1/eth/monad/action/compound) + +#### Description + +This endpoint will craft a compound rewards transaction ready to be signed. It automatically reinvests your accumulated rewards back into your stake position. + +#### Request body parameters + +[`MonadCompoundActionDto`](/staking-api/api-reference#model/monadcompoundactiondto) + +#### Returned + +[`MonadActionResponseDto`](/staking-api/api-reference#model/monadactionresponsedto) + +____ + +### Prepare action + +Gathers signature and unsigned tx: + +- Endpoint: [`/api/v1/eth/monad/action/prepare`](/staking-api/api-reference#tag/eth-monad/post/api/v1/eth/monad/action/prepare) + +#### Description + +Prepare a signed transaction by gathering the provided signatures (r, s, v) with the unsigned transaction hex string: + +#### Request body parameters + +[`EthPrepareActionDto`](/staking-api/api-reference#model/ethprepareactiondto) + +#### Returned + +[`EthPrepareActionResponseDto`](/staking-api/api-reference#model/ethprepareactionresponsedto) + +____ + +### Broadcast action + +Broadcast a signed transaction: + +- Endpoint: [`/api/v1/eth/monad/action/broadcast`](/staking-api/api-reference#tag/eth-monad/post/api/v1/eth/monad/action/broadcast) + +#### Description + +Broadcast a signed transaction. Usually you will broadcast the signed transaction returned in `prepare` previous step: + +#### Request body parameters + +[`EthBroadcastActionDto`](/staking-api/api-reference#model/ethbroadcastactiondto) + +#### Returned + +[`EthBroadcastActionResponseDto`](/staking-api/api-reference#model/ethbroadcastactionresponsedto) + +____ + +### Stake balance + +Get stake balance for the given address: + +- Endpoint: [`/api/v1/eth/monad/stake-balance/{address}`](/staking-api/api-reference#tag/eth-monad/get/api/v1/eth/monad/stake-balance/{address}) + +#### Description + +Get stake balance and rewards information for the given delegator address. All values are returned in ether units. + +#### Request parameters + +At url param you will need to pass the `address` you want to retrieve stake balance from + +#### Returned + +[`GetStakeBalanceResponseDto`](/staking-api/api-reference#model/getstakebalanceresponsedto) + +____ + +### Withdrawal requests + +Get withdrawal requests for the given address: + +- Endpoint: [`/api/v1/eth/monad/withdrawals/{address}`](/staking-api/api-reference#tag/eth-monad/get/api/v1/eth/monad/withdrawals/{address}) + +#### Description + +Get withdrawal requests for the given delegator address. You can optionally filter by withdrawal ID range using query parameters. All values are returned in ether units. + +#### Request parameters + +At url param you will need to pass the `address` you want to retrieve withdrawal requests from + +#### Query parameters + +[`MonadWithdrawalQueryDto`](/staking-api/api-reference#model/monadwithdrawalquerydto) + +- `startWithdrawId` (optional): Start withdrawal ID in the range (0-255, defaults to 0) +- `endWithdrawId` (optional): End withdrawal ID in the range (0-255, defaults to 255) + +#### Returned + +[`GetWithdrawalRequestsResponseDto`](/staking-api/api-reference#model/getwithdrawalrequestsresponsedto) + +____ + +### Withdrawal request + +Get a single withdrawal request: + +- Endpoint: [`/api/v1/eth/monad/withdrawal/{address}/{withdrawId}`](/staking-api/api-reference#tag/eth-monad/get/api/v1/eth/monad/withdrawal/{address}/{withdrawId}) + +#### Description + +Get a single withdrawal request for the given delegator address and withdrawal slot ID. All values are returned in ether units. + +#### Request parameters + +[`MonadWithdrawalParamsDto`](/staking-api/api-reference#model/monadwithdrawalparamsdto) + +- `address`: Delegator address +- `withdrawId`: Withdrawal slot identifier (0-255) + +#### Returned + +[`GetWithdrawalRequestResponseDto`](/staking-api/api-reference#model/getwithdrawalrequestresponsedto) + +____ + diff --git a/docs/staking-api/monad/how-to-sign.md b/docs/staking-api/monad/how-to-sign.md new file mode 100644 index 0000000..0d24740 --- /dev/null +++ b/docs/staking-api/monad/how-to-sign.md @@ -0,0 +1,194 @@ +--- +sidebar_position: 6 +--- +# How to sign + +Once you have completed the first action of the flow (as explained in the diagram), you will need to sign the unsigned transaction. + +There are several ways to achieve this. We will explain a couple of them: + +## Signing with private key + +### Signing with Web3 JS using a Private Key: + +This method involves the use of the Web3 JavaScript library, which allows developers to interact with the Ethreum virtual machine directly from a JavaScript application. To sign a transaction, a developer typically imports the SDK, creates a transaction object, and then uses a private key to sign this object. This signing process is crucial as it verifies the identity of the transaction initiator and ensures the transaction cannot be altered without the initiator's consent. + +Complete with your own wallet private key or seed at `.env` + +``` +ETHEREUM_WALLET_PRIVATE_KEY= +ETHEREUM_RPC= +ETHEREUM_WALLET_ADDRESS= +EVM_CHAIN_ID= +``` + +```javascript +const { Common, Chain, Hardfork } = require('@ethereumjs/common') +const { Web3 } = require('web3'); +const Transaction = require('@ethereumjs/tx'); +const { RLP } = require('@ethereumjs/rlp'); + +const ethUtil = require('ethereumjs-util'); +const { ethers } = require("ethers"); +const path = require('path'); +require('dotenv').config({ path: path.join(__dirname, './../.env') }) + +const accountFrom = { + address: process.env.ETHEREUM_WALLET_ADDRESS, + privateKey: process.env.ETHEREUM_WALLET_PRIVATE_KEY, + rpcEndpoint: process.env.ETHEREUM_RPC, + chainId: process.env.EVM_CHAIN_ID +}; + +const web3 = new Web3(ETHEREUM_RPC); +const common = new Common({ chain: accountFrom.chainId }) + +const signUnsignedTxWithPk = async ({serialized_tx_hex, raw_tx_hex_hash}) => { + const serializedTxBytes = await web3.utils.hexToBytes(serialized_tx_hex); + const rawTxHexHashWithoutPrefix = raw_tx_hex_hash.substring(2); + + const txObject = Transaction.TransactionFactory.fromSerializedData(serializedTxBytes, { common }); + + const txJson = txObject.toJSON(); + + let num = BigInt(txJson.nonce); + + const nonceNormalized = num === 0n ? num : txJson.nonce; + const params = [nonceNormalized, txJson.gasPrice, txJson.gasLimit, txJson.to, txJson.value, txJson.data]; + + const rawTransaction = RLP.encode(params); + + const privateKeyBuffer = Buffer.from(accountFrom.privateKey, 'hex'); + + const txHashBytes = Buffer.from(rawTxHexHashWithoutPrefix, 'hex'); + + const signResult = ethUtil.ecsign(txHashBytes, privateKeyBuffer, Number(accountFrom.chainId)); + + const rBuff = signResult.r; + const sBuff = signResult.s; + const r = rBuff.toString('hex'); + const s = sBuff.toString('hex'); + const v = signResult.v; + + return { r, s, v}; +} +// Get serialized_tx_hex and raw_tx_hex_hash from stake action response (reference at doc models StakeActionResponseDTO) + +const signature = await signUnsignedTxWithPk({serialized_tx_hex, raw_tx_hex_hash}) +// With the Signature you need to pass it to the /prepare endpoint +// Check api reference + +``` + +1. Get the `serialized_tx_hex` and `raw_tx_hex_hash` from any of the Stake actions +2. Pass it to the signer code explaind below +3. Once you have the signature proceed calling `action/prepare` + + +## Signing by using external custodian integration + +### Fireblocks + +Using external custodian services such as [Fireblocks](https://www.fireblocks.com/) provides an additional layer of security for transaction signing. + +Fireblocks, as a custodian, manages the private keys on behalf of the user, ensuring they are stored securely and are not exposed during the transaction process. + +To sign a transaction, the transaction details are sent to Fireblocks via its API. + +Fireblocks then signs the transaction securely within its infrastructure and returns the signed transaction, ready for submission to the blockchain network. + +On the code example we will be providing a Javascript example with the usage of [Fireblocks SDK JS/TS](https://github.com/fireblocks/fireblocks-sdk-js) + + +Complete with your own Fireblocks credentials at `.env` + +``` +FIREBLOCKS_API_SECRET= +FIREBLOCKS_API_KEY= +FIREBLOCKS_BASE_URL= +FIREBLOCKS_VAULT_ID= +``` + +```javascript + +const { FireblocksSDK, TransactionOperation, PeerType, TransactionStatus } = require("fireblocks-sdk") + +const apiSecret = process.env.FIREBLOCKS_API_SECRET; +const apiKey = process.env.FIREBLOCKS_API_KEY; +const baseUrl = process.env.FIREBLOCKS_BASE_URL; +const vaultId = process.env.FIREBLOCKS_VAULT_ID; + +const fireblocks = new FireblocksSDK(apiSecret, apiKey, baseUrl); + +const waitForTxCompletion = async (fbTx) => { + try { + let tx = fbTx; + while (tx.status != TransactionStatus.COMPLETED) { + if ( + tx.status == TransactionStatus.BLOCKED || + tx.status == TransactionStatus.FAILED || + tx.status == TransactionStatus.CANCELLED + ) { + throw Error(`Fireblocks signer: the transaction has been ${tx.status}`); + } else if (tx.status == TransactionStatus.REJECTED) { + throw Error( + `Fireblocks signer: the transaction has been rejected, make sure that the TAP security policy is not blocking the transaction`, + ); + } + tx = await fireblocks.getTransactionById(fbTx.id); + } + + return await fireblocks.getTransactionById(fbTx.id); + } catch (err) { + throw new Error("Fireblocks signer (waitForTxCompletion): " + err); + } +} + +const signWithFb = async (unsigned_tx_hash_hex) => { + const assetId = "ETH"; + const rawTxHexHashWithoutPrefix = rawTxHexHash.substring(2); + + const tx = { + assetId: assetId, + operation: TransactionOperation.RAW, + source: { + type: PeerType.VAULT_ACCOUNT, + id: vaultId + }, + note: "Sign transaction from stakely staking api", + "extraParameters": { + "rawMessageData": { + "messages": [ + { + "content": rawTxHexHashWithoutPrefix + } + ] + } + } + }; + const fbTx = await fireblocks.createTransaction(tx); + const result = await waitForTxCompletion(fbTx); + const signature = result.signedMessages[0].signature; + + const v = 27 + signature.v; + const r = '0x'+signature.r; + const s = '0x'+signature.s; + + return { r, s, v}; +} + +// Get raw_tx_hex_hash from stake action response (reference at doc models StakeActionResponseDTO) + + +const signature_hex = await signWithFb(raw_tx_hex_hash); + +// With the Signature you need to pass it to the /prepare endpoint +// Check api reference + +``` + +**Steps:** + +1. Get the `unsigned_tx_hash_hex` from any of the Stake actions +2. Pass it to the signer code explaind below +3. Once you have the signature proceed calling `action/prepare` \ No newline at end of file diff --git a/docs/staking-api/monad/network-information.md b/docs/staking-api/monad/network-information.md new file mode 100644 index 0000000..57bb9fa --- /dev/null +++ b/docs/staking-api/monad/network-information.md @@ -0,0 +1,13 @@ +--- +sidebar_position: 1 +--- +# Network Information + +:::info +This API interacts with the **Monad** blockchain network. +::: + +You can find more technical network documentation and parameters related to staking in the following links: +- https://docs.monad.xyz +- https://stakely.io/staking/monad-staking + diff --git a/docs/staking-api/monad/staking-api-diagram.md b/docs/staking-api/monad/staking-api-diagram.md new file mode 100644 index 0000000..eedc13e --- /dev/null +++ b/docs/staking-api/monad/staking-api-diagram.md @@ -0,0 +1,42 @@ +--- +sidebar_position: 2 +--- +# Staking API Diagram + +```mermaid +sequenceDiagram +autonumber +actor User +participant Staking API +User->>+Staking API: Delegate action +Note left of User: Offline: Delegate 1 ETH +Note right of Staking API: 🔨 Delegate action crafting +Staking API-->>-User: Delegate action return +activate User +rect rgb(255,178,216) +Note left of User: 📝 Sign unsigned transaction: +Note left of User: a) Locally with private key 🔑 +Note left of User: b) Custodian 🏦 +end +deactivate User + +User->>+Staking API: Prepare +Note right of Staking API: 🔏 Adds signature to tx +Staking API-->>-User: Returns signed transaction +activate User +rect rgba(228, 173, 77, 0.8) +Note left of User: With the signed transaction you can: +Note left of User: Broadcast it by yourself using any RPC +Note left of User: Send it to the broadcast endpoint +end +deactivate User +User->>+Staking API: Broadcast +Note right of Staking API: 📡 Broadcast to the network +Staking API-->>-User: Returns broadcasted transaction status +activate User +rect rgba(50, 156, 0, 0.8) +Note left of User: If success, transaction is already onchain! 🚀 +end +deactivate User +``` + diff --git a/docs/staking-api/solana/_category_.json b/docs/staking-api/solana/_category_.json index f057d50..ff9b713 100644 --- a/docs/staking-api/solana/_category_.json +++ b/docs/staking-api/solana/_category_.json @@ -1,8 +1,7 @@ { "label": "Solana", - "position": 6, "link": { "type": "generated-index", - "description": "Staking API Cosmos Hub documentation" + "description": "Staking API Solana documentation" } } diff --git a/docs/staking-api/supported-network.md b/docs/staking-api/supported-network.md index a1e4b8c..896ce63 100644 --- a/docs/staking-api/supported-network.md +++ b/docs/staking-api/supported-network.md @@ -7,7 +7,8 @@ sidebar_position: 3 This page provides a comprehensive list of the blockchain networks currently supported by Stakely's Staking API. Our goal is to facilitate a wide range of staking operations across various blockchain ecosystems. Please note that this list is updated regularly to reflect new additions and updates to our supported networks. ## Currently Supported Networks -| Blockchain | Crafting API | Reporting API | + +| Blockchain | Crafting API | Reporting API | | --------------- | ------------ | ------------ | | Cosmos Hub | ✅ | ❌ | | Celestia | ✅ | ❌ | @@ -16,11 +17,11 @@ This page provides a comprehensive list of the blockchain networks currently sup | Ethereum (native) | ✅ | ❌ | | Ethereum mainnet (Stakewise) | ✅ | ❌ | | Ethereum hoodi (Stakewise) | ✅ | ❌ | +| Monad | ✅ | ❌ | | Solana | ✅ | ❌ | | Injective | ❌ | ❌ | | Sui | ❌ | ❌ | - ## Requesting Support for New Networks -We are always looking to broaden our support to meet the needs of our users. If there is a network you wish to see supported by our Staking API that is not listed here, please do not hesitate to contact us. \ No newline at end of file +We are always looking to broaden our support to meet the needs of our users. If there is a network you wish to see supported by our Staking API that is not listed here, please do not hesitate to contact us.