Skip to content

Commit

Permalink
add kava (#112)
Browse files Browse the repository at this point in the history
* add kava

* update readme

* nit

* nit

* nit
  • Loading branch information
nooxx authored Aug 1, 2024
1 parent 9840226 commit d56cb86
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 2 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ Check out the [full documentation](https://docs.kiln.fi/v1/connect/overview).
- ADA
- ATOM
- DOT
- KSM
- DYDX
- ETH
- FET
- INJ
- KAVA
- KSM
- MATIC
- NEAR
- NOBLE
Expand Down
3 changes: 2 additions & 1 deletion src/integrations/fb_signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ export type AssetId =
| "CELESTIA"
| "INJ_INJ"
| "TON_TEST"
| "TON";
| "TON"
| "KAVA_KAVA";

export class FbSigner {
protected fireblocks: FireblocksSDK;
Expand Down
3 changes: 3 additions & 0 deletions src/kiln.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { TonService } from "./services/ton";
import { XtzService } from "./services/xtz";
import { ZetaService } from "./services/zeta";
import { KILN_VALIDATORS as v } from "./validators";
import { KavaService } from "./services/kava";

type Config = {
apiToken: string;
Expand Down Expand Up @@ -48,6 +49,7 @@ export class Kiln {
inj: InjService;
ton: TonService;
zeta: ZetaService;
kava: KavaService;

constructor({ testnet, apiToken, baseUrl }: Config) {
api.defaults.headers.common.Authorization = `Bearer ${apiToken}`;
Expand All @@ -73,5 +75,6 @@ export class Kiln {
this.inj = new InjService({ testnet });
this.ton = new TonService({ testnet });
this.zeta = new ZetaService({ testnet });
this.kava = new KavaService({ testnet });
}
}
177 changes: 177 additions & 0 deletions src/services/kava.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import { Service } from "./service";

import { ServiceProps } from "../types/service";
import { Integration } from "../types/integrations";
import api from "../api";
import { DecodedTxRaw } from "@cosmjs/proto-signing";
import { CosmosSignedTx, CosmosTx, CosmosTxHash, CosmosTxStatus } from "../types/cosmos";
import { parseUnits } from "viem";

export class KavaService extends Service {
constructor({ testnet }: ServiceProps) {
super({ testnet });
}

/**
* Convert KAVA to ukava
* @param amount
*/
kavaToUkava(amount: string): string {
return parseUnits(amount, 6).toString();
}

/**
* Craft kava staking transaction
* @param accountId id of the kiln account to use for the stake transaction
* @param pubkey wallet pubkey, this is different from the wallet address
* @param validatorAddress validator address to delegate to
* @param amountKava how many tokens to stake in KAVA
* @param restakeRewards If enabled, the rewards will be automatically restaked
* @param granteeAddress validator grantee address
*/
async craftStakeTx(
accountId: string,
pubkey: string,
validatorAddress: string,
amountKava: number,
restakeRewards: boolean = false,
granteeAddress?: string,
): Promise<CosmosTx> {
const { data } = await api.post<CosmosTx>(`/v1/kava/transaction/stake`, {
account_id: accountId,
pubkey: pubkey,
validator: validatorAddress,
amount_ukava: this.kavaToUkava(amountKava.toString()),
restake_rewards: restakeRewards,
grantee_address: granteeAddress,
});
return data;
}

/**
* Craft kava withdraw rewards transaction
* @param pubkey wallet pubkey, this is different from the wallet address
* @param validatorAddress validator address to which the delegation has been made
*/
async craftWithdrawRewardsTx(pubkey: string, validatorAddress: string): Promise<CosmosTx> {
const { data } = await api.post<CosmosTx>(`/v1/kava/transaction/withdraw-rewards`, {
pubkey: pubkey,
validator: validatorAddress,
});
return data;
}

/**
* Craft kava restake rewards transaction
* @param pubkey wallet pubkey, this is different from the wallet address
* @param validatorAddress validator address to which the delegation has been made
* @param granteeAddress validator grantee address
*/
async craftRestakeRewardsTx(pubkey: string, validatorAddress: string, granteeAddress: string): Promise<CosmosTx> {
const { data } = await api.post<CosmosTx>(`/v1/kava/transaction/restake-rewards`, {
pubkey: pubkey,
validator_address: validatorAddress,
grantee_address: granteeAddress,
});
return data;
}

/**
* Craft kava unstaking transaction
* @param pubkey wallet pubkey, this is different from the wallet address
* @param validatorAddress validator address to which the delegation has been made
* @param amountKava how many tokens to undelegate in KAVA
*/
async craftUnstakeTx(pubkey: string, validatorAddress: string, amountKava?: number): Promise<CosmosTx> {
const { data } = await api.post<CosmosTx>(`/v1/kava/transaction/unstake`, {
pubkey: pubkey,
validator: validatorAddress,
amount_kava: amountKava ? this.kavaToUkava(amountKava.toString()) : undefined,
});
return data;
}

/**
* Craft kava redelegate transaction
* @param accountId id of the kiln account to use for the new stake
* @param pubkey wallet pubkey, this is different from the wallet address
* @param validatorSourceAddress validator address of the current delegation
* @param validatorDestinationAddress validator address to which the delegation will be moved
* @param amountKava how many tokens to redelegate in KAVA
*/
async craftRedelegateTx(
accountId: string,
pubkey: string,
validatorSourceAddress: string,
validatorDestinationAddress: string,
amountKava?: number,
): Promise<CosmosTx> {
const { data } = await api.post<CosmosTx>(`/v1/kava/transaction/redelegate`, {
account_id: accountId,
pubkey: pubkey,
validator_source: validatorSourceAddress,
validator_destination: validatorDestinationAddress,
amount_ukava: amountKava ? this.kavaToUkava(amountKava.toString()) : undefined,
});
return data;
}

/**
* Sign transaction with given integration
* @param integration custody solution to sign with
* @param tx raw transaction
* @param note note to identify the transaction in your custody solution
*/
async sign(integration: Integration, tx: CosmosTx, note?: string): Promise<CosmosSignedTx> {
const payload = {
rawMessageData: {
messages: [
{
content: tx.data.unsigned_tx_hash,
},
],
},
};
const fbNote = note ? note : "KAVA tx from @kilnfi/sdk";
const signer = this.getFbSigner(integration);
const fbTx = await signer.sign(payload, "KAVA_KAVA", fbNote);
const signature: string = fbTx.signedMessages![0].signature.fullSig;
const { data } = await api.post<CosmosSignedTx>(`/v1/kava/transaction/prepare`, {
pubkey: tx.data.pubkey,
tx_body: tx.data.tx_body,
tx_auth_info: tx.data.tx_auth_info,
signature: signature,
});
data.data.fireblocks_tx = fbTx;
return data;
}

/**
* Broadcast transaction to the network
* @param signedTx
*/
async broadcast(signedTx: CosmosSignedTx): Promise<CosmosTxHash> {
const { data } = await api.post<CosmosTxHash>(`/v1/kava/transaction/broadcast`, {
tx_serialized: signedTx.data.signed_tx_serialized,
});
return data;
}

/**
* Get transaction status
* @param txHash
*/
async getTxStatus(txHash: string): Promise<CosmosTxStatus> {
const { data } = await api.get<CosmosTxStatus>(`/v1/kava/transaction/status?tx_hash=${txHash}`);
return data;
}

/**
* Decode transaction
* @param txSerialized transaction serialized
*/
async decodeTx(txSerialized: string): Promise<DecodedTxRaw> {
const { data } = await api.get<DecodedTxRaw>(`/v1/kava/transaction/decode?tx_serialized=${txSerialized}`);
return data;
}
}

0 comments on commit d56cb86

Please sign in to comment.