Staking API Tutorial
An example showing how to send a Cosmos transaction using the Blockdaemon Staking API.
Here is a TypeScript example showing how to send a Cosmos transaction using the Staking API.
import { fromBase64, toBase64 } from '@cosmjs/encoding';
import { SignDoc, TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
import { isDeliverTxSuccess, StargateClient } from '@cosmjs/stargate';
import { HttpEndpoint, Tendermint34Client } from '@cosmjs/tendermint-rpc';
import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
async function getAddress(wallet: DirectSecp256k1HdWallet): Promise<string> {
const acc = await wallet.getAccounts();
if (acc.length < 1) throw 'Not enough account in the wallet';
if (!acc[0]) throw 'Invalid account in the wallet';
return acc[0].address;
}
export async function broadcastTx(
client: StargateClient,
bytes: Uint8Array,
): Promise<boolean> {
try {
const broadcastResponse = await client.broadcastTx(bytes);
return broadcastResponse && isDeliverTxSuccess(broadcastResponse);
} catch (err) {
console.error(err);
}
return false;
}
async function signAndCommit(
cosmos: StargateClient,
wallet: DirectSecp256k1HdWallet,
tx: string,
) {
if (!tx) throw 'Transaction is undefined';
const signDoc = SignDoc.decode(fromBase64(tx));
const { signature, signed } = await wallet.signDirect(
await getAddress(wallet),
signDoc,
);
const txRaw = TxRaw.fromPartial({
bodyBytes: signed.bodyBytes,
authInfoBytes: signed.authInfoBytes,
signatures: [fromBase64(signature.signature)],
});
const txRawBytes = TxRaw.encode(txRaw).finish();
await broadcastTx(cosmos, txRawBytes);
}
async function createStake() {
// get environment variables
const { wallet_mnemonic, bossApiKey, clientId, rpcEndpoint } =
getCosmosVariables();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(wallet_mnemonic);
const delegator_address = await getAddress(wallet);
console.log(`Delegator address is: ${delegator_address}`);
// create a stake intent with the Staking Reporting API
const response = await createStakeIntent(bossApiKey, clientId, {
delegator_address: delegator_address,
amount: '10000000',
});
if (!response.cosmos) {
throw 'Missing property `cosmos` in BOSS responce';
}
// get the unsigned transaction data returned by the Staking Reporting API
const unsigned_transaction = response.cosmos.unsigned_transaction;
const cosmosClient = await StargateClient.connect(rpcEndpoint);
await signAndCommit(cosmosClient, wallet, unsigned_transaction);
}
async function deativateStake() {
// get environment variables
const { wallet_mnemonic, bossApiKey, clientId, rpcEndpoint } =
getCosmosVariables();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(wallet_mnemonic);
const delegator_address = await getAddress(wallet);
console.log(`Delegator address is: ${delegator_address}`);
// create a stake intent with the Staking Reporting API
const response = await createDeactivateionIntent(bossApiKey, clientId, {
delegator_address: delegator_address,
amount: '1000000',
});
if (!response.cosmos) {
throw 'Missing property `cosmos` in BOSS responce';
}
// get the unsigned transaction data returned by the Staking Reporting API
const unsigned_transaction = response.cosmos.unsigned_transaction;
const cosmosClient = await StargateClient.connect(rpcEndpoint);
await signAndCommit(cosmosClient, wallet, unsigned_transaction);
}
async function rewardsWithdrawal() {
// get environment variables
const { wallet_mnemonic, bossApiKey, clientId, rpcEndpoint } =
getCosmosVariables();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(wallet_mnemonic);
const delegator_address = await getAddress(wallet);
console.log(`Delegator address is: ${delegator_address}`);
// create a stake intent with the Staking Reporting API
const response = await createRewardsWithdrawalIntent(bossApiKey, clientId, {
delegator_address: delegator_address,
});
if (!response.cosmos) {
throw 'Missing property `cosmos` in BOSS responce';
}
// get the unsigned transaction data returned by the Staking Reporting API
const unsigned_transaction = response.cosmos.unsigned_transaction;
const cosmosClient = await StargateClient.connect(rpcEndpoint);
await signAndCommit(cosmosClient, wallet, unsigned_transaction);
}
// a function for getting environment variables
function getCosmosVariables() {
// check for the BOSS API key
if (!process.env['BOSS_API_KEY']) {
throw new Error('Please set the BOSS_API_KEY env variable.');
}
// check for the cosmos wallet mnemonic
if (!process.env['WALLET_MNEMONIC']) {
throw new Error(
'Please set the WALLET_MNEMONIC env variable. It should be base58 encoded',
);
}
// check for the Staking Reporting client id
if (!process.env['CLIENT_ID']) {
throw new Error('Please set the CLIENT_ID env variable');
}
// check for the Coscmos rpc endpoint
if (!process.env['COSMO_RPC_ENDPOINT']) {
throw new Error('Please set the CLIENT_ID env variable');
}
return {
wallet_mnemonic: process.env['WALLET_MNEMONIC'],
bossApiKey: process.env['BOSS_API_KEY'],
clientId: process.env['CLIENT_ID'],
rpcEndpoint: process.env['COSMO_RPC_ENDPOINT'],
};
}
export type StakeIntentCosmosRequest = {
delegator_address: string;
amount: string;
};
export type DeactivationIntentCosmosRequest = {
delegator_address: string;
amount: string;
};
export type RewardsWithdrawalIntentCosmosRequest = {
delegator_address: string;
};
export type StakeIntentCosmos = {
base_address: string;
pool_id: string;
unsigned_transaction: string;
};
export type DeactivationIntentResponce = {
deactivate_intent_id: string;
protocol: string;
network: string;
cosmos?: StakeIntentCosmos;
customer_id?: string;
};
export type RewardsWithdrawalIntentResponce = {
protocol: string;
network: string;
cosmos?: StakeIntentCosmos;
customer_id?: string;
};
export type StakeIntentResponce = {
stake_intent_id: string;
protocol: string;
network: string;
cosmos?: StakeIntentCosmos;
customer_id?: string;
};
/* a function for creating a stake intent with the BOSS API */
function createStakeIntent(
bossApiKey: string,
clientId: string,
request: StakeIntentCosmosRequest,
): Promise<StakeIntentResponce> {
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'X-API-Key': bossApiKey,
'X-Client-ID': clientId,
},
body: JSON.stringify(request),
};
const network = 'testnet';
// return the response from POST Create a New Stake Intent
return fetch(
`${process.env['BOSS_API_ADDRESS']}/v1/cosmos/${network}/stake-intents`,
requestOptions,
).then(async (response: any) => {
if (response.status != 200) {
throw await response.json();
}
return response.json() as Promise<StakeIntentResponce>;
});
}
function createDeactivateionIntent(
bossApiKey: string,
clientId: string,
request: DeactivationIntentCosmosRequest,
): Promise<StakeIntentResponce> {
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'X-API-Key': bossApiKey,
'X-Client-ID': clientId,
},
body: JSON.stringify(request),
};
const network = 'testnet';
// return the response from POST Create a New Stake Intent
return fetch(
`${process.env['BOSS_API_ADDRESS']}/v1/cosmos/${network}/deactivation-intents`,
requestOptions,
).then(async (response: any) => {
if (response.status != 200) {
throw await response.json();
}
return response.json() as Promise<StakeIntentResponce>;
});
}
function createRewardsWithdrawalIntent(
bossApiKey: string,
clientId: string,
request: RewardsWithdrawalIntentCosmosRequest,
): Promise<StakeIntentResponce> {
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'X-API-Key': bossApiKey,
'X-Client-ID': clientId,
},
body: JSON.stringify(request),
};
const network = 'testnet';
// return the response from POST Create a New Stake Intent
return fetch(
`${process.env['BOSS_API_ADDRESS']}/v1/cosmos/${network}/rewards/withdrawal-intents`,
requestOptions,
).then(async (response: any) => {
if (response.status != 200) {
throw await response.json();
}
return response.json() as Promise<StakeIntentResponce>;
});
}
// run the example
// createStake()
// .then(() => process.exit(0))
// .catch(err => {
// console.error(err);
// process.exit(1);
// });
// deativateStake()
// .then(() => process.exit(0))
// .catch(err => {
// console.error(err);
// process.exit(1);
// });
rewardsWithdrawal()
.then(() => process.exit(0))
.catch(err => {
console.error(err);
process.exit(1);
});
👋 Need Help?
Contact us through email or our support page for any issues, bugs, or assistance you may need.
Updated about 1 month ago